Skip to content

Commit 991e2a5

Browse files
authored
Simplify benchmark test suite (#959)
1 parent 5d9ae86 commit 991e2a5

File tree

4 files changed

+109
-123
lines changed

4 files changed

+109
-123
lines changed

.github/workflows/bench.yml

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,7 @@ jobs:
1717
strategy:
1818
matrix:
1919
e2e_runner: [node, bun]
20-
products_size:
21-
# The results don't change that much based on the list size,
22-
# But later we might want them back
23-
# - 10
24-
# - 100
25-
- 1000
26-
name: ${{matrix.e2e_runner}} / ${{matrix.products_size}} items
20+
name: ${{matrix.e2e_runner}}
2721
runs-on: ubuntu-latest
2822
steps:
2923
- name: Checkout
@@ -35,5 +29,4 @@ jobs:
3529
- name: Bench
3630
run: ${{matrix.e2e_runner == 'bun' && './node_modules/.bin/bun' || 'yarn'}} bench
3731
env:
38-
PRODUCTS_SIZE: ${{matrix.products_size}}
3932
E2E_GATEWAY_RUNNER: ${{matrix.e2e_runner}}

bench/federation/federation.bench.ts

Lines changed: 32 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ function memoize1<T extends (...args: any) => any>(fn: T): T {
3232

3333
describe('Federation', async () => {
3434
const { fs } = createTenv(__dirname);
35-
const { query, operationName, result, supergraph } =
36-
createExampleSetup(__dirname);
35+
const { query, operationName, result, supergraph } = createExampleSetup(
36+
__dirname,
37+
1000,
38+
);
3739
const services: Record<string, { schema: GraphQLSchema }> = {
3840
accounts,
3941
inventory,
@@ -75,9 +77,21 @@ describe('Federation', async () => {
7577
throw new Error(`Operation ${operationName} not found`);
7678
}
7779

78-
let apolloGW: ApolloGateway;
79-
let apolloGWSchema: GraphQLSchema;
80-
let apolloGWExecutor: ApolloGateway['executor'];
80+
const apolloGW = new ApolloGateway({
81+
logger: dummyLogger,
82+
supergraphSdl,
83+
buildService({ name }) {
84+
const lowercasedName = name.toLowerCase();
85+
const service = services[lowercasedName];
86+
if (!service) {
87+
throw new Error(`Service ${name} not found`);
88+
}
89+
return new LocalGraphQLDataSource(service.schema);
90+
},
91+
});
92+
93+
let { schema: apolloGWSchema, executor: apolloGWExecutor } =
94+
await apolloGW.load();
8195

8296
const schemaHash: string & { __fauxpaque: 'SchemaHash' } = Object.assign(
8397
new String(supergraphSdl) as string,
@@ -111,32 +125,20 @@ describe('Federation', async () => {
111125
},
112126
);
113127
},
114-
{
115-
async setup() {
116-
apolloGW = new ApolloGateway({
117-
logger: dummyLogger,
118-
supergraphSdl,
119-
buildService({ name }) {
120-
const lowercasedName = name.toLowerCase();
121-
const service = services[lowercasedName];
122-
if (!service) {
123-
throw new Error(`Service ${name} not found`);
124-
}
125-
return new LocalGraphQLDataSource(service.schema);
126-
},
127-
});
128-
const { schema, executor } = await apolloGW.load();
129-
apolloGWSchema = schema;
130-
apolloGWExecutor = executor;
131-
},
132-
teardown() {
133-
return apolloGW.stop();
134-
},
135-
...benchConfig,
136-
},
128+
benchConfig,
137129
);
138130

139-
let stitchedSchema: GraphQLSchema;
131+
const stitchedSchema = getStitchedSchemaFromSupergraphSdl({
132+
supergraphSdl,
133+
onSubschemaConfig(subschemaConfig) {
134+
const lowercasedName = subschemaConfig.name.toLowerCase();
135+
const service = services[lowercasedName];
136+
if (!service) {
137+
throw new Error(`Service ${subschemaConfig.name} not found`);
138+
}
139+
subschemaConfig.executor = createDefaultExecutor(service.schema);
140+
},
141+
});
140142

141143
bench(
142144
'Stitching',
@@ -153,21 +155,6 @@ describe('Federation', async () => {
153155
expect(response).toEqual(result);
154156
},
155157
),
156-
{
157-
setup() {
158-
stitchedSchema = getStitchedSchemaFromSupergraphSdl({
159-
supergraphSdl,
160-
onSubschemaConfig(subschemaConfig) {
161-
const lowercasedName = subschemaConfig.name.toLowerCase();
162-
const service = services[lowercasedName];
163-
if (!service) {
164-
throw new Error(`Service ${subschemaConfig.name} not found`);
165-
}
166-
subschemaConfig.executor = createDefaultExecutor(service.schema);
167-
},
168-
});
169-
},
170-
...benchConfig,
171-
},
158+
benchConfig,
172159
);
173160
});
Lines changed: 46 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,60 @@
1-
import { ApolloGateway } from '@apollo/gateway';
2-
import { ApolloServer } from '@apollo/server';
3-
import { startStandaloneServer } from '@apollo/server/standalone';
4-
import { createExampleSetup, createTenv, Gateway } from '@internal/e2e';
5-
import { benchConfig } from '@internal/testing';
1+
import {
2+
createExampleSetup,
3+
createTenv,
4+
Gateway,
5+
Service,
6+
} from '@internal/e2e';
7+
import { benchConfig, getLocalhost } from '@internal/testing';
68
import { fetch } from '@whatwg-node/fetch';
79
import { bench, describe, expect } from 'vitest';
810

911
describe('Gateway', async () => {
10-
const { gateway, fs } = createTenv(__dirname);
11-
const example = createExampleSetup(__dirname);
12+
const { gateway, service } = createTenv(__dirname);
13+
const example = createExampleSetup(__dirname, 1000);
1214

1315
const supergraph = await example.supergraph();
14-
const supergraphSdl = await fs.read(supergraph);
1516

16-
let apolloGw: ApolloServer;
17-
let apolloGwUrl: string;
18-
let ctrl: AbortController;
19-
bench(
20-
'Apollo Gateway',
21-
async () => {
22-
const res = await fetch(`${apolloGwUrl}/graphql`, {
23-
method: 'POST',
24-
headers: {
25-
'Content-Type': 'application/json',
26-
},
27-
body: JSON.stringify({
28-
query: example.query,
29-
}),
30-
signal: ctrl.signal,
31-
});
32-
const data = await res.json();
33-
expect(data).toEqual({
34-
data: expect.any(Object),
35-
});
36-
},
37-
{
38-
async setup() {
39-
ctrl = new AbortController();
40-
apolloGw = new ApolloServer({
41-
gateway: new ApolloGateway({
42-
supergraphSdl,
43-
}),
44-
});
45-
const { url } = await startStandaloneServer(apolloGw, {
46-
listen: { port: 0 },
47-
});
48-
apolloGwUrl = url;
17+
const gateways: Record<string, Gateway | Service> = {
18+
'Apollo Gateway': await service('apollo-gateway', {
19+
env: {
20+
SUPERGRAPH: supergraph,
4921
},
50-
teardown() {
51-
ctrl.abort();
52-
return apolloGw.stop();
22+
}),
23+
'Hive Gateway': await gateway({
24+
supergraph,
25+
args: ['--jit'],
26+
env: {
27+
JIT: 'true',
28+
NODE_ENV: 'production',
5329
},
54-
...benchConfig,
55-
},
56-
);
30+
}),
31+
};
5732

58-
let hiveGw: Gateway;
59-
bench(
60-
'Hive Gateway',
61-
async () => {
62-
const res = await hiveGw.execute({
63-
query: example.query,
64-
});
65-
expect(res).toEqual(example.result);
66-
},
67-
{
68-
async setup() {
69-
hiveGw = await gateway({
70-
supergraph,
71-
args: ['--jit'],
72-
env: {
73-
NODE_ENV: 'production',
74-
JIT: 'true',
33+
for (const gwName in gateways) {
34+
const gw = gateways[gwName];
35+
if (!gw) {
36+
throw new Error(`Gateway ${gwName} not found`);
37+
}
38+
const gwPort = gw.port;
39+
const gwHost = await getLocalhost(gwPort, gw.protocol);
40+
const gwUrl = `${gwHost}:${gwPort}/graphql`;
41+
const body = JSON.stringify({
42+
query: example.query,
43+
});
44+
bench(
45+
gwName,
46+
async () => {
47+
const response = await fetch(gwUrl, {
48+
method: 'POST',
49+
headers: {
50+
'Content-Type': 'application/json',
7551
},
52+
body,
7653
});
54+
const data = await response.json();
55+
expect(data).toEqual(example.result);
7756
},
78-
async teardown() {
79-
return hiveGw[Symbol.asyncDispose]();
80-
},
81-
...benchConfig,
82-
},
83-
);
57+
benchConfig,
58+
);
59+
}
8460
});
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { readFileSync } from 'fs';
2+
import { ApolloGateway } from '@apollo/gateway';
3+
import { ApolloServer } from '@apollo/server';
4+
import { startStandaloneServer } from '@apollo/server/standalone';
5+
import { Opts } from '@internal/testing';
6+
7+
const opts = Opts(process.argv);
8+
const port = opts.getServicePort('apollo-gateway');
9+
10+
async function main() {
11+
const supergraph = process.env['SUPERGRAPH'];
12+
if (!supergraph) {
13+
throw new Error('SUPERGRAPH env var is required');
14+
}
15+
const supergraphSdl = readFileSync(supergraph, 'utf-8');
16+
const server = new ApolloServer({
17+
gateway: new ApolloGateway({
18+
supergraphSdl,
19+
}),
20+
});
21+
const { url } = await startStandaloneServer(server, {
22+
listen: { port },
23+
});
24+
console.log(`🚀 Gateway ready at ${url}`);
25+
}
26+
27+
main().catch((error) => {
28+
console.error(error);
29+
process.exit(1);
30+
});

0 commit comments

Comments
 (0)