Skip to content

Commit

Permalink
benchmark: improve accuracy by disabling GC during benchmarks
Browse files Browse the repository at this point in the history
We execute benchmarked code multiple times in a cycle to improve
accuracy but this also leads to GC being triggered that significantly
affect accuracy. To solve this now we allocate 1GB of heap specifically
for new objects. Also trace GC to ensure all our benchmarks fit into
1GB.
  • Loading branch information
IvanGoncharov committed May 25, 2022
1 parent 21ea3ae commit 3075967
Showing 1 changed file with 28 additions and 21 deletions.
49 changes: 28 additions & 21 deletions resources/benchmark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,40 +362,47 @@ function sampleModule(modulePath: string): Promise<BenchmarkSample> {
const sampleCode = `
import assert from 'node:assert';
assert(global.gc);
assert(process.send);
import { benchmark } from '${modulePath}';
clock(7, benchmark.measure); // warm up
global.gc();
process.nextTick(() => {
const memBaseline = process.memoryUsage().heapUsed;
const clocked = clock(benchmark.count, benchmark.measure);
process.send({
name: benchmark.name,
clocked: clocked / benchmark.count,
memUsed: (process.memoryUsage().heapUsed - memBaseline) / benchmark.count,
});
});
// warm up, it looks like 7 is a magic number to reliably trigger JIT
benchmark.measure();
benchmark.measure();
benchmark.measure();
benchmark.measure();
benchmark.measure();
benchmark.measure();
benchmark.measure();
// Clocks the time taken to execute a test per cycle (secs).
function clock(count, fn) {
const start = process.hrtime.bigint();
for (let i = 0; i < count; ++i) {
fn();
}
return Number(process.hrtime.bigint() - start);
const memBaseline = process.memoryUsage().heapUsed;
const startTime = process.hrtime.bigint();
for (let i = 0; i < benchmark.count; ++i) {
benchmark.measure();
}
const timeDiff = Number(process.hrtime.bigint() - startTime);
process.send({
name: benchmark.name,
clocked: timeDiff / benchmark.count,
memUsed: (process.memoryUsage().heapUsed - memBaseline) / benchmark.count,
});
`;

return new Promise((resolve, reject) => {
const child = cp.spawn(
process.execPath,
[
'--no-concurrent-sweeping',
// V8 flags
'--predictable',
'--expose-gc',
'--no-concurrent-sweeping',
'--no-scavenge-task',
'--min-semi-space-size=1024', // 1GB
'--max-semi-space-size=1024', // 1GB
'--trace-gc', // no gc calls should happen during benchmark, so trace them

// Node.js flags
'--input-type=module',
'--eval',
sampleCode,
Expand Down

0 comments on commit 3075967

Please sign in to comment.