Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(NODE-6583): upgrade to BSON v6.10.1 to remove internal unbounded type cache #4338

Merged
merged 11 commits into from
Dec 5, 2024
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
},
"dependencies": {
"@mongodb-js/saslprep": "^1.1.9",
"bson": "^6.10.0",
"bson": "^6.10.1",
"mongodb-connection-string-url": "^3.0.0"
},
"peerDependencies": {
Expand Down
78 changes: 73 additions & 5 deletions test/benchmarks/driverBench/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,72 @@ const fs = require('fs');
const path = require('path');
const { Readable } = require('stream');
const { pipeline } = require('stream/promises');
const { MongoClient } = require('../../..');
const { GridFSBucket } = require('../../..');
// eslint-disable-next-line no-restricted-modules
const { MONGODB_ERROR_CODES } = require('../../../lib/error');
const child_process = require('child_process');

/**
* The path to the MongoDB Node.js driver.
* This MUST be set to the directory the driver is installed in
* NOT the file "lib/index.js" that is the driver's export.
*/
const MONGODB_DRIVER_PATH = (() => {
W-A-James marked this conversation as resolved.
Show resolved Hide resolved
let driverPath = process.env.MONGODB_DRIVER_PATH;
if (!driverPath?.length) {
driverPath = path.resolve(__dirname, '../../..');
}
return driverPath;
})();

const { MongoClient, GridFSBucket } = require(MONGODB_DRIVER_PATH);

/** Grab the version from the package.json */
const { version: MONGODB_DRIVER_VERSION } = require(path.join(MONGODB_DRIVER_PATH, 'package.json'));

/**
* Use git to optionally determine the git revision,
* but the benchmarks could be run against an npm installed version so this should be allowed to fail
*/
const MONGODB_DRIVER_REVISION = (() => {
try {
return child_process
.execSync('git rev-parse --short HEAD', {
cwd: MONGODB_DRIVER_PATH,
encoding: 'utf8'
})
.trim();
} catch {
return 'unknown revision';
}
})();

/**
* Find the BSON dependency inside the driver PATH given and grab the version from the package.json.
*/
const MONGODB_BSON_PATH = path.join(MONGODB_DRIVER_PATH, 'node_modules', 'bson');
const { version: MONGODB_BSON_VERSION } = require(path.join(MONGODB_BSON_PATH, 'package.json'));

/**
* If you need to test BSON changes, you should clone, checkout and build BSON.
* run: `npm link` with no arguments to register the link.
* Then in the driver you are testing run `npm link bson` to use your local build.
*
* This will symlink the BSON into the driver's node_modules directory. So here
* we can find the revision of the BSON we are testing against if .git exists.
*/
const MONGODB_BSON_REVISION = (() => {
if (!fs.existsSync(path.join(MONGODB_BSON_PATH, '.git'))) {
return 'installed from npm';
}
try {
return child_process
.execSync('git rev-parse --short HEAD', {
cwd: path.join(MONGODB_BSON_PATH),
encoding: 'utf8'
})
.trim();
} catch {
return 'unknown revision';
}
})();

const DB_NAME = 'perftest';
const COLLECTION_NAME = 'corpus';
Expand Down Expand Up @@ -67,7 +129,7 @@ function initCollection() {

function dropCollection() {
return this.collection.drop().catch(e => {
if (e.code !== MONGODB_ERROR_CODES.NamespaceNotFound) {
if (e.code !== 26 /* NamespaceNotFound */) {
W-A-James marked this conversation as resolved.
Show resolved Hide resolved
throw e;
}
});
Expand Down Expand Up @@ -117,6 +179,12 @@ async function writeSingleByteFileToBucket() {
module.exports = {
MONGODB_URI,
MONGODB_CLIENT_OPTIONS,
MONGODB_DRIVER_PATH,
MONGODB_DRIVER_VERSION,
MONGODB_DRIVER_REVISION,
MONGODB_BSON_PATH,
MONGODB_BSON_VERSION,
MONGODB_BSON_REVISION,
makeClient,
connectClient,
disconnectClient,
Expand Down
24 changes: 18 additions & 6 deletions test/benchmarks/driverBench/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const MongoBench = require('../mongoBench');
const os = require('node:os');
const util = require('node:util');
const process = require('node:process');

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

const { writeFile } = require('fs/promises');
const { makeParallelBenchmarks, makeSingleBench, makeMultiBench } = require('../mongoBench/suites');
const { MONGODB_CLIENT_OPTIONS } = require('./common');
const {
MONGODB_CLIENT_OPTIONS,
MONGODB_DRIVER_PATH,
MONGODB_DRIVER_VERSION,
MONGODB_DRIVER_REVISION,
MONGODB_BSON_PATH,
MONGODB_BSON_VERSION,
MONGODB_BSON_REVISION
} = require('./common');

const hw = os.cpus();
const ram = os.totalmem() / 1024 ** 3;
Expand All @@ -24,7 +33,10 @@ const systemInfo = () =>
`- arch: ${os.arch()}`,
`- os: ${process.platform} (${os.release()})`,
`- ram: ${platform.ram}`,
`- node: ${process.version}\n`
`- node: ${process.version}`,
`- driver: ${MONGODB_DRIVER_VERSION} (${MONGODB_DRIVER_REVISION}): ${MONGODB_DRIVER_PATH}`,
` - options ${util.inspect(MONGODB_CLIENT_OPTIONS)}`,
`- bson: ${MONGODB_BSON_VERSION} (${MONGODB_BSON_REVISION}): (${MONGODB_BSON_PATH})\n`
].join('\n');
console.log(systemInfo());

Expand Down Expand Up @@ -52,8 +64,8 @@ benchmarkRunner
// 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

const parallelBench = average([
microBench.parallel.ldjsonMultiFileUpload ?? 44.02343490518617,
microBench.parallel.ldjsonMultiFileExport ?? 31.83182984813926,
microBench.parallel.ldjsonMultiFileUpload,
microBench.parallel.ldjsonMultiFileExport,
microBench.parallel.gridfsMultiFileUpload,
microBench.parallel.gridfsMultiFileDownload
]);
Expand All @@ -63,15 +75,15 @@ benchmarkRunner
microBench.multiBench.findManyAndEmptyCursor,
microBench.multiBench.gridFsDownload,
microBench.parallel.gridfsMultiFileDownload,
microBench.parallel.ldjsonMultiFileExport ?? 31.83182984813926
microBench.parallel.ldjsonMultiFileExport
]);
const writeBench = average([
microBench.singleBench.smallDocInsertOne,
microBench.singleBench.largeDocInsertOne,
microBench.multiBench.smallDocBulkInsert,
microBench.multiBench.largeDocBulkInsert,
microBench.multiBench.gridFsUpload,
microBench.parallel.ldjsonMultiFileUpload ?? 44.02343490518617,
microBench.parallel.ldjsonMultiFileUpload,
microBench.parallel.gridfsMultiFileUpload
]);

Expand Down
78 changes: 39 additions & 39 deletions test/benchmarks/mongoBench/suites/parallelBench.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ const {
dropBucket,
initCollection,
initDb,
connectClient
connectClient,
dropCollection,
createCollection
} = require('../../driverBench/common');
const { pipeline } = require('stream/promises');
const { EJSON } = require('bson');
Expand All @@ -34,7 +36,6 @@ async function clearTemporaryDirectory() {
await Promise.all(files.map(file => rm(file)));
}

// eslint-disable-next-line no-unused-vars
async function ldjsonMultiUpload() {
const directory = resolve(benchmarkFileDirectory, 'ldjson_multi');
const files = await readdir(directory);
Expand Down Expand Up @@ -63,7 +64,6 @@ async function ldjsonMultiUpload() {
await Promise.all(uploads);
}

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

Expand Down Expand Up @@ -113,43 +113,43 @@ async function gridfsMultiFileDownload() {
* @returns Benchmark
*/
function makeParallelBenchmarks(suite) {
// .benchmark('ldjsonMultiFileUpload', benchmark =>
// // https://github.com/mongodb/specifications/blob/master/source/benchmarking/benchmarking.rst#ldjson-multi-file-import
// benchmark
// .taskSize(565)
// .setup(makeClient)
// .setup(connectClient)
// .setup(initDb)
// .setup(dropDb)
// .beforeTask(initCollection)
// .beforeTask(dropCollection)
// .beforeTask(createCollection)
// .task(ldjsonMultiUpload)
// .teardown(dropDb)
// .teardown(disconnectClient)
// )
// .benchmark('ldjsonMultiFileExport', benchmark =>
// // https://github.com/mongodb/specifications/blob/master/source/benchmarking/benchmarking.rst#ldjson-multi-file-export
// benchmark
// .taskSize(565)
// .setup(makeClient)
// .setup(connectClient)
// .setup(initDb)
// .setup(dropDb)
// .beforeTask(initCollection)
// .beforeTask(dropCollection)
// .beforeTask(createCollection)
// .beforeTask(ldjsonMultiUpload)
// .beforeTask(initTemporaryDirectory)
// .task(ldjsonMultiExport)
// .afterTask(clearTemporaryDirectory)
// .teardown(dropDb)
// .teardown(async function () {
// await rm(this.temporaryDirectory, { recursive: true, force: true });
// })
// .teardown(disconnectClient)
// )
return suite
.benchmark('ldjsonMultiFileUpload', benchmark =>
// https://github.com/mongodb/specifications/blob/master/source/benchmarking/benchmarking.rst#ldjson-multi-file-import
benchmark
.taskSize(565)
.setup(makeClient)
.setup(connectClient)
.setup(initDb)
.setup(dropDb)
.beforeTask(initCollection)
.beforeTask(dropCollection)
.beforeTask(createCollection)
.task(ldjsonMultiUpload)
.teardown(dropDb)
.teardown(disconnectClient)
)
.benchmark('ldjsonMultiFileExport', benchmark =>
// https://github.com/mongodb/specifications/blob/master/source/benchmarking/benchmarking.rst#ldjson-multi-file-export
benchmark
.taskSize(565)
.setup(makeClient)
.setup(connectClient)
.setup(initDb)
.setup(dropDb)
.beforeTask(initCollection)
.beforeTask(dropCollection)
.beforeTask(createCollection)
.beforeTask(ldjsonMultiUpload)
.beforeTask(initTemporaryDirectory)
.task(ldjsonMultiExport)
.afterTask(clearTemporaryDirectory)
.teardown(dropDb)
.teardown(async function () {
await rm(this.temporaryDirectory, { recursive: true, force: true });
})
.teardown(disconnectClient)
)
.benchmark('gridfsMultiFileUpload', benchmark =>
// https://github.com/mongodb/specifications/blob/master/source/benchmarking/benchmarking.rst#gridfs-multi-file-upload
benchmark
Expand Down
54 changes: 54 additions & 0 deletions test/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,60 @@ beforeEach(() => {
});
```

## Running Benchmarks

```sh
npm run check:bench
```

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.

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.

The host used is described in detail here: https://spruce.mongodb.com/distro/rhel90-dbx-perf-large/settings/general (Auth required to view)

Here is a rough list of the key configurations:

- cpu: Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz
- cores: 16
- arch: x64
- os: RHEL 9.0 linux (5.14.0-70.75.1.el9_0.x86_64)
- ram: 64 GB

It is best to try reproductions against as similar a deployment as possible to isolate regressions.

### Configuration

The benchmarks can be directed to test different settings and driver versions.

The following are environment variables and how the benchmark runner uses them:

- `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.
- `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.
- `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.

It may be desirable to test how changes to `BSON` impact the driver's performance.

To do this:
- clone the changed version of BSON
- run the build script for that repo (usually done by `npm install` for you)
- run `npm link`
- over in the driver repo run `npm link bson`

When you run the benchmarks verify that the BSON version has been picked by the version references that are printed out:

```md
- cpu: Apple M1 Max
- cores: 10
- arch: arm64
- os: darwin (23.6.0)
- ram: 32GB
- node: v22.6.0
- driver: 6.11.0 (df3ea32a9): .../mongodb
- options {}
- bson: 6.10.1 (installed from npm): (.../mongodb/node_modules/bson)
```

## Testing with Special Environments

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.
Expand Down
Loading