Skip to content

Commit 249c279

Browse files
authoredDec 5, 2024··
fix(NODE-6583): upgrade to BSON v6.10.1 to remove internal unbounded type cache (#4338)
1 parent 5558573 commit 249c279

File tree

6 files changed

+189
-55
lines changed

6 files changed

+189
-55
lines changed
 

‎package-lock.json

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
},
2727
"dependencies": {
2828
"@mongodb-js/saslprep": "^1.1.9",
29-
"bson": "^6.10.0",
29+
"bson": "^6.10.1",
3030
"mongodb-connection-string-url": "^3.0.0"
3131
},
3232
"peerDependencies": {

‎test/benchmarks/driverBench/common.js

+73-5
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,72 @@ const fs = require('fs');
44
const path = require('path');
55
const { Readable } = require('stream');
66
const { pipeline } = require('stream/promises');
7-
const { MongoClient } = require('../../..');
8-
const { GridFSBucket } = require('../../..');
9-
// eslint-disable-next-line no-restricted-modules
10-
const { MONGODB_ERROR_CODES } = require('../../../lib/error');
7+
const child_process = require('child_process');
8+
9+
/**
10+
* The path to the MongoDB Node.js driver.
11+
* This MUST be set to the directory the driver is installed in
12+
* NOT the file "lib/index.js" that is the driver's export.
13+
*/
14+
const MONGODB_DRIVER_PATH = (() => {
15+
let driverPath = process.env.MONGODB_DRIVER_PATH;
16+
if (!driverPath?.length) {
17+
driverPath = path.resolve(__dirname, '../../..');
18+
}
19+
return driverPath;
20+
})();
21+
22+
const { MongoClient, GridFSBucket } = require(MONGODB_DRIVER_PATH);
23+
24+
/** Grab the version from the package.json */
25+
const { version: MONGODB_DRIVER_VERSION } = require(path.join(MONGODB_DRIVER_PATH, 'package.json'));
26+
27+
/**
28+
* Use git to optionally determine the git revision,
29+
* but the benchmarks could be run against an npm installed version so this should be allowed to fail
30+
*/
31+
const MONGODB_DRIVER_REVISION = (() => {
32+
try {
33+
return child_process
34+
.execSync('git rev-parse --short HEAD', {
35+
cwd: MONGODB_DRIVER_PATH,
36+
encoding: 'utf8'
37+
})
38+
.trim();
39+
} catch {
40+
return 'unknown revision';
41+
}
42+
})();
43+
44+
/**
45+
* Find the BSON dependency inside the driver PATH given and grab the version from the package.json.
46+
*/
47+
const MONGODB_BSON_PATH = path.join(MONGODB_DRIVER_PATH, 'node_modules', 'bson');
48+
const { version: MONGODB_BSON_VERSION } = require(path.join(MONGODB_BSON_PATH, 'package.json'));
49+
50+
/**
51+
* If you need to test BSON changes, you should clone, checkout and build BSON.
52+
* run: `npm link` with no arguments to register the link.
53+
* Then in the driver you are testing run `npm link bson` to use your local build.
54+
*
55+
* This will symlink the BSON into the driver's node_modules directory. So here
56+
* we can find the revision of the BSON we are testing against if .git exists.
57+
*/
58+
const MONGODB_BSON_REVISION = (() => {
59+
if (!fs.existsSync(path.join(MONGODB_BSON_PATH, '.git'))) {
60+
return 'installed from npm';
61+
}
62+
try {
63+
return child_process
64+
.execSync('git rev-parse --short HEAD', {
65+
cwd: path.join(MONGODB_BSON_PATH),
66+
encoding: 'utf8'
67+
})
68+
.trim();
69+
} catch {
70+
return 'unknown revision';
71+
}
72+
})();
1173

1274
const DB_NAME = 'perftest';
1375
const COLLECTION_NAME = 'corpus';
@@ -67,7 +129,7 @@ function initCollection() {
67129

68130
function dropCollection() {
69131
return this.collection.drop().catch(e => {
70-
if (e.code !== MONGODB_ERROR_CODES.NamespaceNotFound) {
132+
if (e.code !== 26 /* NamespaceNotFound */) {
71133
throw e;
72134
}
73135
});
@@ -117,6 +179,12 @@ async function writeSingleByteFileToBucket() {
117179
module.exports = {
118180
MONGODB_URI,
119181
MONGODB_CLIENT_OPTIONS,
182+
MONGODB_DRIVER_PATH,
183+
MONGODB_DRIVER_VERSION,
184+
MONGODB_DRIVER_REVISION,
185+
MONGODB_BSON_PATH,
186+
MONGODB_BSON_VERSION,
187+
MONGODB_BSON_REVISION,
120188
makeClient,
121189
connectClient,
122190
disconnectClient,

‎test/benchmarks/driverBench/index.js

+18-6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
const MongoBench = require('../mongoBench');
44
const os = require('node:os');
5+
const util = require('node:util');
56
const process = require('node:process');
67

78
const Runner = MongoBench.Runner;
@@ -11,7 +12,15 @@ let bsonType = 'js-bson';
1112

1213
const { writeFile } = require('fs/promises');
1314
const { makeParallelBenchmarks, makeSingleBench, makeMultiBench } = require('../mongoBench/suites');
14-
const { MONGODB_CLIENT_OPTIONS } = require('./common');
15+
const {
16+
MONGODB_CLIENT_OPTIONS,
17+
MONGODB_DRIVER_PATH,
18+
MONGODB_DRIVER_VERSION,
19+
MONGODB_DRIVER_REVISION,
20+
MONGODB_BSON_PATH,
21+
MONGODB_BSON_VERSION,
22+
MONGODB_BSON_REVISION
23+
} = require('./common');
1524

1625
const hw = os.cpus();
1726
const ram = os.totalmem() / 1024 ** 3;
@@ -24,7 +33,10 @@ const systemInfo = () =>
2433
`- arch: ${os.arch()}`,
2534
`- os: ${process.platform} (${os.release()})`,
2635
`- ram: ${platform.ram}`,
27-
`- node: ${process.version}\n`
36+
`- node: ${process.version}`,
37+
`- driver: ${MONGODB_DRIVER_VERSION} (${MONGODB_DRIVER_REVISION}): ${MONGODB_DRIVER_PATH}`,
38+
` - options ${util.inspect(MONGODB_CLIENT_OPTIONS)}`,
39+
`- bson: ${MONGODB_BSON_VERSION} (${MONGODB_BSON_REVISION}): (${MONGODB_BSON_PATH})\n`
2840
].join('\n');
2941
console.log(systemInfo());
3042

@@ -52,8 +64,8 @@ benchmarkRunner
5264
// https://spruce.mongodb.com/task/mongo_node_driver_next_performance_tests_run_spec_benchmark_tests_node_server_4bc3e500b6f0e8ab01f052c4a1bfb782d6a29b4e_f168e1328f821bbda265e024cc91ae54_24_11_18_15_37_24/logs?execution=0
5365

5466
const parallelBench = average([
55-
microBench.parallel.ldjsonMultiFileUpload ?? 44.02343490518617,
56-
microBench.parallel.ldjsonMultiFileExport ?? 31.83182984813926,
67+
microBench.parallel.ldjsonMultiFileUpload,
68+
microBench.parallel.ldjsonMultiFileExport,
5769
microBench.parallel.gridfsMultiFileUpload,
5870
microBench.parallel.gridfsMultiFileDownload
5971
]);
@@ -63,15 +75,15 @@ benchmarkRunner
6375
microBench.multiBench.findManyAndEmptyCursor,
6476
microBench.multiBench.gridFsDownload,
6577
microBench.parallel.gridfsMultiFileDownload,
66-
microBench.parallel.ldjsonMultiFileExport ?? 31.83182984813926
78+
microBench.parallel.ldjsonMultiFileExport
6779
]);
6880
const writeBench = average([
6981
microBench.singleBench.smallDocInsertOne,
7082
microBench.singleBench.largeDocInsertOne,
7183
microBench.multiBench.smallDocBulkInsert,
7284
microBench.multiBench.largeDocBulkInsert,
7385
microBench.multiBench.gridFsUpload,
74-
microBench.parallel.ldjsonMultiFileUpload ?? 44.02343490518617,
86+
microBench.parallel.ldjsonMultiFileUpload,
7587
microBench.parallel.gridfsMultiFileUpload
7688
]);
7789

‎test/benchmarks/mongoBench/suites/parallelBench.js

+39-39
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ const {
1313
dropBucket,
1414
initCollection,
1515
initDb,
16-
connectClient
16+
connectClient,
17+
dropCollection,
18+
createCollection
1719
} = require('../../driverBench/common');
1820
const { pipeline } = require('stream/promises');
1921
const { EJSON } = require('bson');
@@ -34,7 +36,6 @@ async function clearTemporaryDirectory() {
3436
await Promise.all(files.map(file => rm(file)));
3537
}
3638

37-
// eslint-disable-next-line no-unused-vars
3839
async function ldjsonMultiUpload() {
3940
const directory = resolve(benchmarkFileDirectory, 'ldjson_multi');
4041
const files = await readdir(directory);
@@ -63,7 +64,6 @@ async function ldjsonMultiUpload() {
6364
await Promise.all(uploads);
6465
}
6566

66-
// eslint-disable-next-line no-unused-vars
6767
async function ldjsonMultiExport() {
6868
const skips = Array.from({ length: 100 }, (_, index) => index * 5000);
6969

@@ -113,43 +113,43 @@ async function gridfsMultiFileDownload() {
113113
* @returns Benchmark
114114
*/
115115
function makeParallelBenchmarks(suite) {
116-
// .benchmark('ldjsonMultiFileUpload', benchmark =>
117-
// // https://github.com/mongodb/specifications/blob/master/source/benchmarking/benchmarking.rst#ldjson-multi-file-import
118-
// benchmark
119-
// .taskSize(565)
120-
// .setup(makeClient)
121-
// .setup(connectClient)
122-
// .setup(initDb)
123-
// .setup(dropDb)
124-
// .beforeTask(initCollection)
125-
// .beforeTask(dropCollection)
126-
// .beforeTask(createCollection)
127-
// .task(ldjsonMultiUpload)
128-
// .teardown(dropDb)
129-
// .teardown(disconnectClient)
130-
// )
131-
// .benchmark('ldjsonMultiFileExport', benchmark =>
132-
// // https://github.com/mongodb/specifications/blob/master/source/benchmarking/benchmarking.rst#ldjson-multi-file-export
133-
// benchmark
134-
// .taskSize(565)
135-
// .setup(makeClient)
136-
// .setup(connectClient)
137-
// .setup(initDb)
138-
// .setup(dropDb)
139-
// .beforeTask(initCollection)
140-
// .beforeTask(dropCollection)
141-
// .beforeTask(createCollection)
142-
// .beforeTask(ldjsonMultiUpload)
143-
// .beforeTask(initTemporaryDirectory)
144-
// .task(ldjsonMultiExport)
145-
// .afterTask(clearTemporaryDirectory)
146-
// .teardown(dropDb)
147-
// .teardown(async function () {
148-
// await rm(this.temporaryDirectory, { recursive: true, force: true });
149-
// })
150-
// .teardown(disconnectClient)
151-
// )
152116
return suite
117+
.benchmark('ldjsonMultiFileUpload', benchmark =>
118+
// https://github.com/mongodb/specifications/blob/master/source/benchmarking/benchmarking.rst#ldjson-multi-file-import
119+
benchmark
120+
.taskSize(565)
121+
.setup(makeClient)
122+
.setup(connectClient)
123+
.setup(initDb)
124+
.setup(dropDb)
125+
.beforeTask(initCollection)
126+
.beforeTask(dropCollection)
127+
.beforeTask(createCollection)
128+
.task(ldjsonMultiUpload)
129+
.teardown(dropDb)
130+
.teardown(disconnectClient)
131+
)
132+
.benchmark('ldjsonMultiFileExport', benchmark =>
133+
// https://github.com/mongodb/specifications/blob/master/source/benchmarking/benchmarking.rst#ldjson-multi-file-export
134+
benchmark
135+
.taskSize(565)
136+
.setup(makeClient)
137+
.setup(connectClient)
138+
.setup(initDb)
139+
.setup(dropDb)
140+
.beforeTask(initCollection)
141+
.beforeTask(dropCollection)
142+
.beforeTask(createCollection)
143+
.beforeTask(ldjsonMultiUpload)
144+
.beforeTask(initTemporaryDirectory)
145+
.task(ldjsonMultiExport)
146+
.afterTask(clearTemporaryDirectory)
147+
.teardown(dropDb)
148+
.teardown(async function () {
149+
await rm(this.temporaryDirectory, { recursive: true, force: true });
150+
})
151+
.teardown(disconnectClient)
152+
)
153153
.benchmark('gridfsMultiFileUpload', benchmark =>
154154
// https://github.com/mongodb/specifications/blob/master/source/benchmarking/benchmarking.rst#gridfs-multi-file-upload
155155
benchmark

‎test/readme.md

+54
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,60 @@ beforeEach(() => {
241241
});
242242
```
243243

244+
## Running Benchmarks
245+
246+
```sh
247+
npm run check:bench
248+
```
249+
250+
Refer to the `run-spec-benchmark-tests-node-server` task for Node.js version, MongoDB server version, and platform that we run benchmarks against in CI.
251+
252+
The server is run in standalone mode and the server versions are aliased by this script: https://github.com/mongodb-labs/drivers-evergreen-tools/blob/5048cca80e9ca62642409de2d401058bbd7057fa/.evergreen/mongodl.py#L58 check the latest version to see what alias the driver is running against.
253+
254+
The host used is described in detail here: https://spruce.mongodb.com/distro/rhel90-dbx-perf-large/settings/general (Auth required to view)
255+
256+
Here is a rough list of the key configurations:
257+
258+
- cpu: Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz
259+
- cores: 16
260+
- arch: x64
261+
- os: RHEL 9.0 linux (5.14.0-70.75.1.el9_0.x86_64)
262+
- ram: 64 GB
263+
264+
It is best to try reproductions against as similar a deployment as possible to isolate regressions.
265+
266+
### Configuration
267+
268+
The benchmarks can be directed to test different settings and driver versions.
269+
270+
The following are environment variables and how the benchmark runner uses them:
271+
272+
- `MONGODB_DRIVER_PATH` - (default: current working driver) if set MUST be set to the directory a driver version is in, usually another clone of the driver checked out to a different revision.
273+
- `MONGODB_CLIENT_OPTIONS` - (default: empty object) if set MUST be a JSON string that will be parsed and passed as the second argument to the MongoClient constructor.
274+
- `MONGODB_URI` - (default: `mongodb://127.0.0.1:27017`) if set MUST be a valid MongoDB connection string and it will be used as the host the benchmarks will run against.
275+
276+
It may be desirable to test how changes to `BSON` impact the driver's performance.
277+
278+
To do this:
279+
- clone the changed version of BSON
280+
- run the build script for that repo (usually done by `npm install` for you)
281+
- run `npm link`
282+
- over in the driver repo run `npm link bson`
283+
284+
When you run the benchmarks verify that the BSON version has been picked by the version references that are printed out:
285+
286+
```md
287+
- cpu: Apple M1 Max
288+
- cores: 10
289+
- arch: arm64
290+
- os: darwin (23.6.0)
291+
- ram: 32GB
292+
- node: v22.6.0
293+
- driver: 6.11.0 (df3ea32a9): .../mongodb
294+
- options {}
295+
- bson: 6.10.1 (installed from npm): (.../mongodb/node_modules/bson)
296+
```
297+
244298
## Testing with Special Environments
245299

246300
In order to test some features, you will need to generate and set a specialized group of environment variables. The subsections below will walk you through how to generate and set the environment variables for these features.

0 commit comments

Comments
 (0)
Please sign in to comment.