Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .evergreen/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3323,7 +3323,7 @@ tasks:
tags:
- run-spec-benchmark-tests
- performance
exec_timeout_secs: 3600
exec_timeout_secs: 18000
commands:
- command: expansions.update
type: setup
Expand Down
2 changes: 1 addition & 1 deletion .evergreen/generate_evergreen_tasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -756,7 +756,7 @@ function addPerformanceTasks() {
const makePerfTaskNEW = (name, MONGODB_CLIENT_OPTIONS) => ({
name,
tags: ['run-spec-benchmark-tests', 'performance'],
exec_timeout_secs: 3600,
exec_timeout_secs: 18000,
commands: [
updateExpansions({
NODE_LTS_VERSION: 'v22.11.0',
Expand Down
48 changes: 48 additions & 0 deletions test/benchmarks/driver_bench/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Node.js Driver Benchmarks

Set up the driver for development (`npm ci` in the top level of this repo).

Then:

```sh
npm start
```

will build the benchmarks and run them.

## Running individual benchmarks

`main.mjs` loops and launches the bench runner for you.

You can launch `runner.mjs` directly and tell it which benchmark to run.

```sh
node lib/runner.mjs suites/multi_bench/grid_fs_upload.mjs
```

## Writing your own benchmark

In the suites directory you can add a new suite folder or add a new `.mts` file to an existing one.

A benchmark must export the following:

```ts
type BenchmarkModule = {
taskSize: number;
before?: () => Promise<void>;
beforeEach?: () => Promise<void>;
run: () => Promise<void>;
afterEach?: () => Promise<void>;
after?: () => Promise<void>;
};
```

Just like mocha we have once before and once after as well as before each and after each hooks.

The `driver.mts` module is intended to hold various helpers for setup and teardown and help abstract some of the driver API.

## Wishlist

- Make it so runner can handle: `./lib/suites/multi_bench/grid_fs_upload.mjs` as an argument so shell path autocomplete makes it easier to pick a benchmark
- Make `main.mjs` accept a filter of some kind to run some of the benchmarks
- TBD
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { driver, type mongodb } from '../../driver.mjs';

export const taskSize = 16;

let db: mongodb.Db;

export async function before() {
await driver.drop();
await driver.create();

db = driver.db;
}

export async function run() {
await db
.aggregate([
{ $documents: [{}] },
{
$set: {
field: {
$reduce: {
input: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
initialValue: [0],
in: { $concatArrays: ['$$value', '$$value'] }
}
}
}
},
{ $unwind: '$field' },
{ $limit: 1000000 }
])
.toArray();
}

export async function after() {
await driver.drop();
await driver.close();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { driver, type mongodb } from '../../driver.mjs';

export const taskSize = 1500;

let db: mongodb.Db;
let tweet: Record<string, any>;

export async function before() {
await driver.drop();
await driver.create();

tweet = await driver.load('single_and_multi_document/tweet.json', 'json');

db = driver.db;
}

export async function run() {
await db
.aggregate([
{ $documents: [tweet] },
{
$set: {
field: {
$reduce: {
input: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
initialValue: [0],
in: { $concatArrays: ['$$value', '$$value'] }
}
}
}
},
{ $unwind: '$field' },
{ $limit: 1000000 }
])
.toArray();
}

export async function after() {
await driver.drop();
await driver.close();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { driver, type mongodb } from '../../driver.mjs';

export const taskSize = 16.22;

let collection: mongodb.Collection;

export async function before() {
await driver.drop();
await driver.create();

const tweet = await driver.load('single_and_multi_document/tweet.json', 'json');
await driver.insertManyOf(tweet, 10000);

collection = driver.collection;
}

export async function run() {
await collection.find({}).toArray();
}

export async function after() {
await driver.drop();
await driver.close();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Readable, Writable } from 'node:stream';
import { pipeline } from 'node:stream/promises';

import { driver, type mongodb } from '../../driver.mjs';

export const taskSize = 52.43;

let bucket: mongodb.GridFSBucket;
let bin: Uint8Array;
let _id: mongodb.ObjectId;
const devNull = () => new Writable({ write: (_, __, callback) => callback() });

export async function before() {
bin = await driver.load('single_and_multi_document/gridfs_large.bin', 'buffer');
}

export async function beforeEach() {
await driver.drop();
await driver.create();

bucket = driver.bucket;

await bucket.drop().catch(() => null);

// Create the bucket.
const stream = bucket.openUploadStream('gridfstest');
const largeBin = Readable.from(bin);
await pipeline(largeBin, stream);
_id = stream.id;
}

export async function run() {
const downloadStream = bucket.openDownloadStream(_id);
await pipeline(downloadStream, devNull());
}

export async function after() {
await driver.drop();
await driver.close();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Readable } from 'node:stream';
import { pipeline } from 'node:stream/promises';

import { driver, type mongodb } from '../../driver.mjs';

export const taskSize = 52.43;

let bucket: mongodb.GridFSBucket;
let uploadStream: mongodb.GridFSBucketWriteStream;
let bin: Uint8Array;

export async function before() {
bin = await driver.load('single_and_multi_document/gridfs_large.bin', 'buffer');
}

export async function beforeEach() {
await driver.drop();
await driver.create();

bucket = driver.bucket;

await bucket.drop().catch(() => null);

uploadStream = bucket.openUploadStream('gridfstest');

// Create the bucket.
const stream = bucket.openUploadStream('setup-file.txt');
const oneByteFile = Readable.from('a');
await pipeline(oneByteFile, stream);
}

export async function run() {
const uploadData = Readable.from(bin);
await pipeline(uploadData, uploadStream);
}

export async function after() {
await driver.drop();
await driver.close();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { driver, type mongodb } from '../../driver.mjs';

export const taskSize = 27.31;

let collection: mongodb.Collection;
let documents: any[];
let largeDoc: any;

export async function before() {
largeDoc = await driver.load('single_and_multi_document/large_doc.json', 'json');
}

export async function beforeEach() {
await driver.drop();
await driver.create();

// Make new "documents" so the _id field is not carried over from the last run
documents = Array.from({ length: 10 }, () => ({ ...largeDoc })) as any[];

collection = driver.collection;
}

export async function run() {
await collection.insertMany(documents, { ordered: true });
}

export async function after() {
await driver.drop();
await driver.close();
}