Skip to content

Commit

Permalink
feat: add min samples as param (#65)
Browse files Browse the repository at this point in the history
* feat: add minSamples as param to each benchmark

* test: add to minSamples param

* docs: add minSamples in the README

* feat: update comment of minSamples

* chore: fix lint
  • Loading branch information
gusanthiago authored Feb 24, 2025
1 parent b5e1e8b commit 9c6812e
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 6 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ const suite = new Suite({ reporter: false });
* `minTime` {number} Minimum duration for the benchmark to run. **Default:** `0.05` seconds.
* `maxTime` {number} Maximum duration for the benchmark to run. **Default:** `0.5` seconds.
* `repeatSuite` {number} Number of times to repeat benchmark to run. **Default:** `1` times.
* `minSamples` {number} Number minimum of samples the each round. **Default:** `10` samples.
* `fn` {Function|AsyncFunction} The benchmark function. Can be synchronous or asynchronous.
* Returns: {Suite}

Expand Down
3 changes: 3 additions & 0 deletions examples/create-uint32array/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ suite
.add(`new Uint32Array(1024) with 10 repetitions`, {repeatSuite: 10}, function () {
return new Uint32Array(1024);
})
.add(`new Uint32Array(1024) with min samples of 50`, {minSamples: 50}, function() {
return new Uint32Array(1024);
})
.add(`[Managed] new Uint32Array(1024)`, function (timer) {
const assert = require('node:assert');

Expand Down
16 changes: 14 additions & 2 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,16 @@ class Benchmark {
maxTime;
plugins;
repeatSuite;
minSamples;

constructor(name, fn, minTime, maxTime, plugins, repeatSuite) {
constructor(name, fn, minTime, maxTime, plugins, repeatSuite, minSamples) {
this.name = name;
this.fn = fn;
this.minTime = minTime;
this.maxTime = maxTime;
this.plugins = plugins;
this.repeatSuite = repeatSuite;
this.minSamples = minSamples;

this.hasArg = this.fn.length >= 1;
if (this.fn.length > 1) {
Expand Down Expand Up @@ -75,6 +77,8 @@ const defaultBenchOptions = {
maxTime: 0.5,
// Number of times the benchmark will be repeated
repeatSuite: 1,
// Number minimum of samples the each round
minSamples: 10,
};

function throwIfNoNativesSyntax() {
Expand Down Expand Up @@ -133,6 +137,11 @@ class Suite {
"options.repeatSuite",
options.repeatSuite,
);
validateNumber(
options.minSamples,
"options.minSamples",
options.minSamples,
);
}
validateFunction(fn, "fn");

Expand All @@ -143,6 +152,7 @@ class Suite {
options.maxTime,
this.#plugins,
options.repeatSuite,
options.minSamples,
);
this.#benchmarks.push(benchmark);
return this;
Expand Down Expand Up @@ -174,7 +184,7 @@ class Suite {
// Warmup is calculated to reduce noise/bias on the results
const initialIterations = await getInitialIterations(benchmark);
debugBench(
`Starting ${benchmark.name} with minTime=${benchmark.minTime}, maxTime=${benchmark.maxTime}, repeatSuite=${benchmark.repeatSuite}`,
`Starting ${benchmark.name} with minTime=${benchmark.minTime}, maxTime=${benchmark.maxTime}, repeatSuite=${benchmark.repeatSuite}, minSamples=${benchmark.minSamples}`,
);

let result;
Expand All @@ -185,6 +195,7 @@ class Suite {
benchmark,
initialIterations,
benchmark.repeatSuite,
benchmark.minSamples,
);
}
results[i] = result;
Expand All @@ -204,6 +215,7 @@ class Suite {
benchmark,
initialIterations,
repeatSuite: benchmark.repeatSuite,
minSamples: benchmark.minSamples,
});
return new Promise((resolve, reject) => {
worker.on("message", (result) => {
Expand Down
4 changes: 1 addition & 3 deletions lib/lifecycle.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,15 +114,13 @@ async function runBenchmarkOnce(
return { iterations, timeSpent };
}

async function runBenchmark(bench, initialIterations, repeatSuite) {
async function runBenchmark(bench, initialIterations, repeatSuite, minSamples) {
const histogram = new StatisticalHistogram();

const maxDuration = bench.maxTime * timer.scale;
const minSamples = 10;

let totalIterations = 0;
let totalTimeSpent = 0;

for (let i = 0; i < repeatSuite; ++i) {
const { iterations, timeSpent } = await runBenchmarkOnce(bench, histogram, {
initialIterations,
Expand Down
13 changes: 13 additions & 0 deletions test/basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,19 @@ describe("API Interface", () => {
);
}
});

it("minSamples should be a valid number", () => {
for (const r of ["ds", {}, () => {}]) {
assert.throws(
() => {
bench.add("name", { minSamples: r }, noop);
},
{
code: "ERR_INVALID_ARG_TYPE",
},
);
}
});
});
});

Expand Down
2 changes: 1 addition & 1 deletion test/plugin-api-doc.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ describe("plugin API", async () => {
"getReport(string)",
"getResult(string)",
"isSupported()",
"onCompleteBenchmark([number, number, object], {fn, fnStr, hasArg, isAsync, maxTime, minTime, name, plugins, repeatSuite})",
"onCompleteBenchmark([number, number, object], {fn, fnStr, hasArg, isAsync, maxTime, minSamples, minTime, name, plugins, repeatSuite})",
"toJSON(string)",
"toString()",
]);
Expand Down

0 comments on commit 9c6812e

Please sign in to comment.