Skip to content

Commit 6658433

Browse files
ci(NODE-4589): add benchmark testing task to CI (#3385)
1 parent c245d82 commit 6658433

File tree

11 files changed

+233
-144
lines changed

11 files changed

+233
-144
lines changed

.evergreen/config.in.yml

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -879,11 +879,42 @@ functions:
879879
880880
aws s3 cp output/lcov-report s3://mciuploads/mongo-node-driver/${revision}/${version_id}//lcov-report/
881881
882+
"run spec driver benchmarks":
883+
- command: subprocess.exec
884+
type: test
885+
params:
886+
working_dir: "src"
887+
env:
888+
PROJECT_DIRECTORY: ${PROJECT_DIRECTORY}
889+
MONGODB_URI: ${MONGODB_URI}
890+
binary: bash
891+
args:
892+
- ${PROJECT_DIRECTORY}/.evergreen/run-benchmarks.sh
893+
882894
tasks:
883-
- name: "test-serverless"
884-
tags: ["serverless"]
885-
commands:
886-
- func: "run serverless tests"
895+
- name: "test-serverless"
896+
tags: ["serverless"]
897+
commands:
898+
- func: "run serverless tests"
899+
900+
- name: run-spec-benchmark-tests
901+
tags:
902+
- run-spec-benchmark-tests
903+
- performance
904+
exec_timeout_secs: 3600
905+
commands:
906+
- func: install dependencies
907+
vars:
908+
NODE_LTS_NAME: gallium
909+
- func: bootstrap mongo-orchestration
910+
vars:
911+
VERSION: rapid
912+
TOPOLOGY: server
913+
AUTH: noauth
914+
- func: run spec driver benchmarks
915+
- command: perf.send
916+
params:
917+
file: src/results.json
887918

888919
task_groups:
889920
- name: serverless_task_group
@@ -935,3 +966,9 @@ post:
935966

936967
ignore:
937968
- '*.md'
969+
buildvariants:
970+
- name: performance-tests
971+
display_name: Performance Test
972+
run_on: ubuntu1804-large
973+
tasks:
974+
- run-spec-benchmark-tests

.evergreen/config.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,12 +834,41 @@ functions:
834834
npx nyc report -t merged-coverage --reporter=html --report-dir output
835835
836836
aws s3 cp output/lcov-report s3://mciuploads/mongo-node-driver/${revision}/${version_id}//lcov-report/
837+
run spec driver benchmarks:
838+
- command: subprocess.exec
839+
type: test
840+
params:
841+
working_dir: src
842+
env:
843+
PROJECT_DIRECTORY: ${PROJECT_DIRECTORY}
844+
MONGODB_URI: ${MONGODB_URI}
845+
binary: bash
846+
args:
847+
- ${PROJECT_DIRECTORY}/.evergreen/run-benchmarks.sh
837848
tasks:
838849
- name: test-serverless
839850
tags:
840851
- serverless
841852
commands:
842853
- func: run serverless tests
854+
- name: run-spec-benchmark-tests
855+
tags:
856+
- run-spec-benchmark-tests
857+
- performance
858+
exec_timeout_secs: 3600
859+
commands:
860+
- func: install dependencies
861+
vars:
862+
NODE_LTS_NAME: gallium
863+
- func: bootstrap mongo-orchestration
864+
vars:
865+
VERSION: rapid
866+
TOPOLOGY: server
867+
AUTH: noauth
868+
- func: run spec driver benchmarks
869+
- command: perf.send
870+
params:
871+
file: src/results.json
843872
- name: test-latest-server
844873
tags:
845874
- latest
@@ -2205,6 +2234,11 @@ post:
22052234
ignore:
22062235
- '*.md'
22072236
buildvariants:
2237+
- name: performance-tests
2238+
display_name: Performance Test
2239+
run_on: ubuntu1804-large
2240+
tasks:
2241+
- run-spec-benchmark-tests
22082242
- name: ubuntu-18.04-erbium
22092243
display_name: Ubuntu 18.04 Node Erbium
22102244
run_on: ubuntu1804-large

.evergreen/run-benchmarks.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#! /bin/bash
2+
3+
[ -s "$PROJECT_DIRECTORY/node-artifacts/nvm/nvm.sh" ] && source "$PROJECT_DIRECTORY"/node-artifacts/nvm/nvm.sh
4+
5+
export MONGODB_URI=$MONGODB_URI
6+
7+
npm run build:ts
8+
npm run check:bench

test/benchmarks/driverBench/common.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ const COLLECTION_NAME = 'corpus';
1010

1111
const SPEC_DIRECTORY = path.resolve(__dirname, 'spec');
1212

13-
const MONGODB_URL = process.env.MONGODB_URL || 'mongodb://localhost:27017';
14-
1513
function loadSpecFile(filePath, encoding) {
1614
const fp = [SPEC_DIRECTORY].concat(filePath);
1715
return fs.readFileSync(path.join.apply(path, fp), encoding);
@@ -22,7 +20,7 @@ function loadSpecString(filePath) {
2220
}
2321

2422
function makeClient() {
25-
this.client = new MongoClient(MONGODB_URL);
23+
this.client = new MongoClient(process.env.MONGODB_URI || 'mongodb://localhost:27017');
2624
}
2725

2826
function connectClient() {

test/benchmarks/driverBench/index.js

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
'use strict';
22

33
const MongoBench = require('../mongoBench');
4+
const { writeFile } = require('fs/promises');
45

56
const Runner = MongoBench.Runner;
67
const commonHelpers = require('./common');
78

8-
const { LEGACY_HELLO_COMMAND } = require('../../../src/constants');
9-
109
let BSON = require('bson');
1110

1211
try {
@@ -16,6 +15,7 @@ try {
1615
}
1716

1817
const { EJSON } = require('bson');
18+
const { inspect } = require('util');
1919

2020
const makeClient = commonHelpers.makeClient;
2121
const connectClient = commonHelpers.connectClient;
@@ -112,9 +112,7 @@ function runCommand(done) {
112112
if (_id > 10000) {
113113
return done();
114114
}
115-
return this.db.command({ [LEGACY_HELLO_COMMAND]: true }, err =>
116-
err ? done(err) : loop(_id + 1)
117-
);
115+
return this.db.command({ hello: true }, err => (err ? done(err) : loop(_id + 1)));
118116
};
119117

120118
return loop(1);
@@ -333,6 +331,8 @@ const benchmarkRunner = new Runner()
333331
benchmarkRunner
334332
.run()
335333
.then(microBench => {
334+
// TODO - test against different BSON versions in CI
335+
// const bsonType = BSON.serialize.toString().includes('native code') ? 'bson-ext' : 'js-bson';
336336
const bsonBench = average(Object.values(microBench.bsonBench));
337337
const singleBench = average([
338338
microBench.singleBench.findOne,
@@ -357,21 +357,31 @@ benchmarkRunner
357357
microBench.multiBench.gridFsUpload
358358
// TODO: Add parallelBench write benchmarks
359359
]);
360-
const driverBench = average([readBench, writeBench]);
361360

362-
return {
363-
microBench,
361+
const benchmarkResults = {
364362
bsonBench,
365363
singleBench,
366364
multiBench,
367365
parallelBench,
368366
readBench,
369367
writeBench,
370-
driverBench
368+
...microBench.bsonBench,
369+
...microBench.singleBench,
370+
...microBench.multiBench
371371
};
372+
373+
return Object.entries(benchmarkResults).map(([benchmarkName, result]) => {
374+
return {
375+
info: {
376+
test_name: benchmarkName
377+
},
378+
metrics: [{ name: 'megabytes_per_second', value: result }]
379+
};
380+
});
372381
})
373382
.then(data => {
374-
data.bsonType = BSON.serialize.toString().includes('native code') ? 'bson-ext' : 'js-bson';
375-
console.log(data);
383+
const results = JSON.stringify(data, undefined, 2);
384+
console.error(inspect(results, { depth: Infinity }));
385+
return writeFile('results.json', results);
376386
})
377387
.catch(err => console.error(err));

test/benchmarks/mongoBench/benchmark.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
'use strict';
22

3-
const util = require('./util');
4-
53
class Benchmark {
64
constructor() {
75
// The Task itself
@@ -165,10 +163,24 @@ class Benchmark {
165163
}
166164

167165
/**
166+
* Converts an array of task functions into a single async function, that awaits each
167+
* task function and resolves once all are completed.
168+
*
169+
* The returned function will reject if any of the task functions fails.
170+
*
168171
* @param {any} arr
172+
* @return {() => Promise<void>}
169173
*/
170174
_convertArrayToAsyncPipeFn(arr) {
171-
return arr.length ? util.asyncChain(arr) : util.noop;
175+
const array = arr.length ? arr : [];
176+
return async function () {
177+
// copy the array to guard against modification
178+
const chain = [].concat(array);
179+
const context = this;
180+
for (const fn of chain) {
181+
await fn.call(context);
182+
}
183+
};
172184
}
173185
}
174186

test/benchmarks/mongoBench/constants.js

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,18 @@
11
'use strict';
22

3-
const SECOND_TO_NS = 1e9;
43
const MINUTE_TO_MS = 60 * 1e3;
54
const FIVE_MINUTES_TO_MS = MINUTE_TO_MS * 5;
65

7-
function parseIntOrDefault(val, def) {
8-
if (!val) {
9-
return def;
10-
}
6+
const DEFAULT_MIN_EXECUTION_TIME =
7+
Number.parseInt(process.env.DRIVER_BENCH_MIN_EX_TIME, 10) || MINUTE_TO_MS;
118

12-
const parsed = Number.parseInt(val, 10);
13-
return parsed ? parsed : def;
14-
}
9+
const DEFAULT_MAX_EXECUTION_TIME =
10+
Number.parseInt(process.env.DRIVER_BENCH_MAX_EX_TIME, 10) || FIVE_MINUTES_TO_MS;
1511

16-
const DEFAULT_MIN_EXECUTION_TIME = parseIntOrDefault(
17-
process.env.DRIVER_BENCH_MIN_EX_TIME,
18-
MINUTE_TO_MS
19-
);
20-
const DEFAULT_MAX_EXECUTION_TIME = parseIntOrDefault(
21-
process.env.DRIVER_BENCH_MAX_EX_TIME,
22-
FIVE_MINUTES_TO_MS
23-
);
24-
const DEFAULT_MIN_EXECUTION_COUNT = parseIntOrDefault(process.env.DRIVER_BENCH_MIN_EX_COUNT, 100);
12+
const DEFAULT_MIN_EXECUTION_COUNT =
13+
Number.parseInt(process.env.DRIVER_BENCH_MIN_EX_COUNT, 10) || 100;
2514

2615
module.exports = {
27-
SECOND_TO_NS,
2816
DEFAULT_MIN_EXECUTION_COUNT,
2917
DEFAULT_MIN_EXECUTION_TIME,
3018
DEFAULT_MAX_EXECUTION_TIME

test/benchmarks/mongoBench/index.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
'use strict';
22

33
module.exports = {
4-
Runner: require('./runner'),
5-
asyncChain: require('./util').asyncChain
4+
Runner: require('./runner')
65
};

0 commit comments

Comments
 (0)