Skip to content

Commit 37ddc71

Browse files
committed
chore: skip ldjsonMultiFileUpload and use file to store data
1 parent 2f3fb46 commit 37ddc71

File tree

3 files changed

+158
-126
lines changed

3 files changed

+158
-126
lines changed

test/benchmarks/driverBench/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ benchmarkRunner
4747
const multiBench = average(Object.values(microBench.multiBench));
4848

4949
const parallelBench = average([
50-
microBench.parallel.ldjsonMultiFileUpload,
50+
microBench.parallel.ldjsonMultiFileUpload ?? 0,
5151
microBench.parallel.ldjsonMultiFileExport,
5252
microBench.parallel.gridfsMultiFileUpload,
5353
microBench.parallel.gridfsMultiFileDownload
@@ -66,7 +66,7 @@ benchmarkRunner
6666
microBench.multiBench.smallDocBulkInsert,
6767
microBench.multiBench.largeDocBulkInsert,
6868
microBench.multiBench.gridFsUpload,
69-
microBench.parallel.ldjsonMultiFileUpload,
69+
microBench.parallel.ldjsonMultiFileUpload ?? 0,
7070
microBench.parallel.gridfsMultiFileUpload
7171
]);
7272

test/benchmarks/mongoBench/runner.js

Lines changed: 73 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@
33
const CONSTANTS = require('./constants');
44
const { performance } = require('perf_hooks');
55
const Suite = require('./suite');
6-
7-
const PERCENTILES = [10, 25, 50, 75, 95, 98, 99];
8-
function percentileIndex(percentile, total) {
9-
return Math.max(Math.floor((total * percentile) / 100 - 1), 0);
10-
}
6+
const fs = require('fs');
7+
const child_process = require('child_process');
8+
const stream = require('stream/promises');
9+
const { Writable } = require('stream');
1110

1211
function timeSyncTask(task, ctx) {
1312
const start = performance.now();
@@ -25,30 +24,54 @@ async function timeAsyncTask(task, ctx) {
2524
return (end - start) / 1000;
2625
}
2726

27+
const awkFindMiddle = [
28+
// For each line, store the line in the array `a` with the current line number as the index
29+
'{ a[NR] = $0 }',
30+
// After processing all lines (END block), calculate the middle index based on the total line count (NR)
31+
'END {',
32+
// Calculate `mid` as the integer division of the line count by 2
33+
' mid = int(NR / 2);',
34+
// If the line count is odd, print the middle line (one-based index: mid + 1)
35+
' if (NR % 2)',
36+
' print a[mid + 1];',
37+
// If the line count is even, print the two middle lines
38+
' else',
39+
' print a[mid], a[mid + 1];',
40+
'}'
41+
].join(' ');
42+
2843
/**
2944
* Returns the execution time for the benchmarks in mb/second
3045
*
3146
* This function internally calculates the 50th percentile execution time and uses
3247
* that as the median.
3348
*
3449
* @param {Benchmark} benchmark
35-
* @param {{ rawData: number[], count: number}} data
3650
* @returns number
3751
*/
38-
function calculateMicroBench(benchmark, data) {
39-
const rawData = data.rawData;
40-
const count = data.count;
52+
async function calculateMicroBench(benchmark) {
53+
const pipeOptions = { stdio: ['pipe', 'pipe', 'inherit'] };
54+
const sort = child_process.spawn('sort', ['-n'], pipeOptions);
55+
const awk = child_process.spawn('awk', [awkFindMiddle], pipeOptions);
56+
57+
let lines = '';
58+
const collect = new Writable({
59+
write: (chunk, encoding, callback) => {
60+
lines += encoding === 'buffer' ? chunk.toString('utf8') : chunk;
61+
callback();
62+
}
63+
});
4164

42-
const sortedData = [].concat(rawData).sort();
65+
await stream.pipeline(fs.createReadStream('raw.dat', 'utf8'), sort.stdin);
66+
await stream.pipeline(sort.stdout, awk.stdin);
67+
await stream.pipeline(awk.stdout, collect);
4368

44-
const percentiles = PERCENTILES.reduce((acc, pct) => {
45-
acc[pct] = sortedData[percentileIndex(pct, count)];
46-
return acc;
47-
}, {});
69+
fs.unlinkSync('raw.dat');
4870

49-
const medianExecution = percentiles[50];
71+
const [value0, value1] = lines.trim().split(' ');
72+
const median = value1 ? (Number(value0) + Number(value1)) / 2 : Number(value0);
5073

51-
return benchmark.taskSize / medianExecution;
74+
return benchmark.taskSize / median;
5275
}
5376

5477
class Runner {
@@ -126,6 +149,7 @@ class Runner {
126149
for (const [name, benchmark] of benchmarks) {
127150
this.reporter(` Executing Benchmark "${name}"`);
128151
result[name] = await this._runBenchmark(benchmark);
152+
this.reporter(` Executed Benchmark "${name}" =`, result[name]);
129153
}
130154

131155
return result;
@@ -142,11 +166,12 @@ class Runner {
142166
const ctx = {};
143167
try {
144168
await benchmark.setup.call(ctx);
145-
const result = await this._loopTask(benchmark, ctx);
169+
await this._loopTask(benchmark, ctx);
146170
await benchmark.teardown.call(ctx);
147-
return calculateMicroBench(benchmark, result);
171+
return await calculateMicroBench(benchmark);
148172
} catch (error) {
149-
return this._errorHandler(error);
173+
fs.unlinkSync('raw.dat');
174+
this._errorHandler(error);
150175
}
151176
}
152177

@@ -157,33 +182,38 @@ class Runner {
157182
* @returns {{ rawData: number[], count: number}}
158183
*/
159184
async _loopTask(benchmark, ctx) {
160-
const start = performance.now();
161-
const rawData = [];
162-
const minExecutionCount = this.minExecutionCount;
163-
const minExecutionTime = this.minExecutionTime;
164-
const maxExecutionTime = this.maxExecutionTime;
165-
let time = performance.now() - start;
166-
let count = 1;
167-
168-
const taskTimer = benchmark._taskType === 'sync' ? timeSyncTask : timeAsyncTask;
169-
170-
while (time < maxExecutionTime && (time < minExecutionTime || count < minExecutionCount)) {
171-
await benchmark.beforeTask.call(ctx);
172-
const executionTime = await taskTimer(benchmark.task, ctx);
173-
rawData.push(executionTime);
174-
count++;
175-
time = performance.now();
185+
const rawDataFile = fs.openSync('raw.dat', 'w');
186+
try {
187+
const start = performance.now();
188+
const minExecutionCount = this.minExecutionCount;
189+
const minExecutionTime = this.minExecutionTime;
190+
const maxExecutionTime = this.maxExecutionTime;
191+
let time = performance.now() - start;
192+
let count = 1;
193+
194+
const taskTimer = benchmark._taskType === 'sync' ? timeSyncTask : timeAsyncTask;
195+
196+
while (time < maxExecutionTime && (time < minExecutionTime || count < minExecutionCount)) {
197+
await benchmark.beforeTask.call(ctx);
198+
const executionTime = await taskTimer(benchmark.task, ctx);
199+
fs.writeSync(rawDataFile, String(executionTime) + '\n');
200+
count++;
201+
time = performance.now();
202+
}
203+
} finally {
204+
fs.closeSync(rawDataFile);
176205
}
177-
178-
return {
179-
rawData,
180-
count
181-
};
182206
}
183207

184-
_errorHandler(e) {
185-
console.error(e);
186-
return NaN;
208+
_errorHandler(error) {
209+
let currentError = error;
210+
while (currentError) {
211+
this.reporter(
212+
`${currentError !== error ? 'Caused by' : 'Error'}: ${currentError.name} - ${currentError.message} - ${currentError.stack}`
213+
);
214+
currentError = currentError.cause;
215+
}
216+
throw error;
187217
}
188218
}
189219

test/benchmarks/mongoBench/suites/parallelBench.js

Lines changed: 83 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -113,87 +113,89 @@ async function gridfsMultiFileDownload() {
113113
* @returns Benchmark
114114
*/
115115
function makeParallelBenchmarks(suite) {
116-
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-
)
153-
.benchmark('gridfsMultiFileUpload', benchmark =>
154-
// https://github.com/mongodb/specifications/blob/master/source/benchmarking/benchmarking.rst#gridfs-multi-file-upload
155-
benchmark
156-
.taskSize(262.144)
157-
.setup(makeClient)
158-
.setup(connectClient)
159-
.setup(initDb)
160-
.setup(dropDb)
161-
.setup(initDb)
162-
.setup(initCollection)
163-
.beforeTask(dropBucket)
164-
.beforeTask(initBucket)
165-
.beforeTask(async function () {
166-
const stream = this.bucket.openUploadStream('setup-file.txt');
167-
const oneByteFile = Readable.from('a');
168-
return pipeline(oneByteFile, stream);
169-
})
170-
.task(gridfsMultiFileUpload)
171-
.teardown(dropDb)
172-
.teardown(disconnectClient)
173-
)
174-
.benchmark('gridfsMultiFileDownload', benchmark =>
175-
// https://github.com/mongodb/specifications/blob/master/source/benchmarking/benchmarking.rst#gridfs-multi-file-download
176-
benchmark
177-
.taskSize(262.144)
178-
.setup(makeClient)
179-
.setup(connectClient)
180-
.setup(initDb)
181-
.setup(dropDb)
182-
.setup(initDb)
183-
.setup(initCollection)
184-
.setup(initTemporaryDirectory)
185-
.setup(dropBucket)
186-
.setup(initBucket)
187-
.setup(gridfsMultiFileUpload)
188-
.beforeTask(clearTemporaryDirectory)
189-
.setup(initBucket)
190-
.task(gridfsMultiFileDownload)
191-
.teardown(dropDb)
192-
.teardown(async function () {
193-
await rm(this.temporaryDirectory, { recursive: true, force: true });
194-
})
195-
.teardown(disconnectClient)
196-
);
116+
return (
117+
suite
118+
// .benchmark('ldjsonMultiFileUpload', benchmark =>
119+
// // https://github.com/mongodb/specifications/blob/master/source/benchmarking/benchmarking.rst#ldjson-multi-file-import
120+
// benchmark
121+
// .taskSize(565)
122+
// .setup(makeClient)
123+
// .setup(connectClient)
124+
// .setup(initDb)
125+
// .setup(dropDb)
126+
// .beforeTask(initCollection)
127+
// .beforeTask(dropCollection)
128+
// .beforeTask(createCollection)
129+
// .task(ldjsonMultiUpload)
130+
// .teardown(dropDb)
131+
// .teardown(disconnectClient)
132+
// )
133+
.benchmark('ldjsonMultiFileExport', benchmark =>
134+
// https://github.com/mongodb/specifications/blob/master/source/benchmarking/benchmarking.rst#ldjson-multi-file-export
135+
benchmark
136+
.taskSize(565)
137+
.setup(makeClient)
138+
.setup(connectClient)
139+
.setup(initDb)
140+
.setup(dropDb)
141+
.beforeTask(initCollection)
142+
.beforeTask(dropCollection)
143+
.beforeTask(createCollection)
144+
.beforeTask(ldjsonMultiUpload)
145+
.beforeTask(initTemporaryDirectory)
146+
.task(ldjsonMultiExport)
147+
.afterTask(clearTemporaryDirectory)
148+
.teardown(dropDb)
149+
.teardown(async function () {
150+
await rm(this.temporaryDirectory, { recursive: true, force: true });
151+
})
152+
.teardown(disconnectClient)
153+
)
154+
.benchmark('gridfsMultiFileUpload', benchmark =>
155+
// https://github.com/mongodb/specifications/blob/master/source/benchmarking/benchmarking.rst#gridfs-multi-file-upload
156+
benchmark
157+
.taskSize(262.144)
158+
.setup(makeClient)
159+
.setup(connectClient)
160+
.setup(initDb)
161+
.setup(dropDb)
162+
.setup(initDb)
163+
.setup(initCollection)
164+
.beforeTask(dropBucket)
165+
.beforeTask(initBucket)
166+
.beforeTask(async function () {
167+
const stream = this.bucket.openUploadStream('setup-file.txt');
168+
const oneByteFile = Readable.from('a');
169+
return pipeline(oneByteFile, stream);
170+
})
171+
.task(gridfsMultiFileUpload)
172+
.teardown(dropDb)
173+
.teardown(disconnectClient)
174+
)
175+
.benchmark('gridfsMultiFileDownload', benchmark =>
176+
// https://github.com/mongodb/specifications/blob/master/source/benchmarking/benchmarking.rst#gridfs-multi-file-download
177+
benchmark
178+
.taskSize(262.144)
179+
.setup(makeClient)
180+
.setup(connectClient)
181+
.setup(initDb)
182+
.setup(dropDb)
183+
.setup(initDb)
184+
.setup(initCollection)
185+
.setup(initTemporaryDirectory)
186+
.setup(dropBucket)
187+
.setup(initBucket)
188+
.setup(gridfsMultiFileUpload)
189+
.beforeTask(clearTemporaryDirectory)
190+
.setup(initBucket)
191+
.task(gridfsMultiFileDownload)
192+
.teardown(dropDb)
193+
.teardown(async function () {
194+
await rm(this.temporaryDirectory, { recursive: true, force: true });
195+
})
196+
.teardown(disconnectClient)
197+
)
198+
);
197199
}
198200

199201
module.exports = { makeParallelBenchmarks };

0 commit comments

Comments
 (0)