Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ const suite = new Suite({ reporter: false });

* `name` {string} The name of the benchmark, displayed when reporting results.
* `options` {Object} Configuration options for the benchmark. Supported properties:
* `minTime` {number} Minimum duration for the benchmark to run. **Default:** `0.05` seconds.
* `minTime` {number} The minimum duration of each sampling interval. **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.
Expand Down
40 changes: 17 additions & 23 deletions lib/lifecycle.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,15 @@ const {
const { StatisticalHistogram } = require("./histogram");

/**
* @param {number} durationPerOp The amount of time each operation takes
* @param {number} targetTime The amount of time we want the benchmark to execute
* @param {number} durationPerOp The amount of time each operation takes, in timer.scale
* @param {number} targetTime The amount of time we want the benchmark to execute, in seconds
* @return {number} - a suggested iteration count >= 1
*/
function getItersForOpDuration(durationPerOp, targetTime) {
const totalOpsForMinTime = targetTime / (durationPerOp / timer.scale);
const secondsPerOp = durationPerOp / timer.scale;
const opsForTargetTime = Math.round(targetTime / secondsPerOp);

return Math.min(
Number.MAX_SAFE_INTEGER,
Math.max(1, Math.round(totalOpsForMinTime)),
);
return Math.min(Number.MAX_SAFE_INTEGER, Math.max(1, opsForTargetTime));
}

function parsePluginsResult(plugins, name) {
Expand Down Expand Up @@ -46,7 +45,7 @@ async function getInitialIterations(bench) {
);

// TODO: is this a correct assumpion?
if (durationPerOp / timer.scale >= bench.maxTime)
if (durationPerOp > bench.maxTime * timer.scale)
process.emitWarning(
`The benchmark "${bench.name}" has a duration per operation greater than the maxTime.`,
);
Expand All @@ -59,8 +58,8 @@ async function getInitialIterations(bench) {
* @param {import('./index').Benchmark} bench - The benchmark object to be executed
* @param {number} initialIterations - The initial number of iterations to run
* @param {Object} options - Warmup options
* @param {number} [options.minTime] - Minimum time for warmup, defaults to bench.minTime
* @param {number} [options.maxTime] - Maximum time for warmup, defaults to bench.minTime
* @param {number} [options.minTime] - Minimum time for warmup, in seconds. Defaults to bench.minTime
* @param {number} [options.maxTime] - Maximum time for warmup, in seconds. Defaults to bench.minTime
* @returns {Promise<void>}
*/
async function runWarmup(bench, initialIterations, { minTime, maxTime }) {
Expand All @@ -86,12 +85,10 @@ async function runWarmup(bench, initialIterations, { minTime, maxTime }) {

// Just to avoid issues with empty fn
const durationPerOp = Math.max(MIN_RESOLUTION, duration / realIterations);
const remainingTime = Math.max(0, (maxDuration - timeSpent) / timer.scale);
const targetTime = Math.min(remainingTime, minTime);

const minWindowTime = Math.max(
0,
Math.min((maxDuration - timeSpent) / timer.scale, minTime),
);
initialIterations = getItersForOpDuration(durationPerOp, minWindowTime);
initialIterations = getItersForOpDuration(durationPerOp, targetTime);
samples++;
}
}
Expand Down Expand Up @@ -125,19 +122,16 @@ async function runBenchmarkOnce(
);
timeSpent += duration;

iterations += realIterations;
iterations = Math.min(Number.MAX_SAFE_INTEGER, iterations);
iterations = Math.min(Number.MAX_SAFE_INTEGER, iterations + realIterations);

// Just to avoid issues with empty fn
const durationPerOp = Math.max(MIN_RESOLUTION, duration / realIterations);

histogram.record(durationPerOp);

const minWindowTime = Math.max(
0,
Math.min((maxDuration - timeSpent) / timer.scale, bench.minTime),
);
initialIterations = getItersForOpDuration(durationPerOp, minWindowTime);
const remainingTime = Math.max(0, (maxDuration - timeSpent) / timer.scale);
const targetTime = Math.min(remainingTime, bench.minTime);
initialIterations = getItersForOpDuration(durationPerOp, targetTime);
}

return { iterations, timeSpent };
Expand Down Expand Up @@ -186,8 +180,8 @@ async function runBenchmark(
}
histogram.finish();

const opsSec = totalIterations / (totalTimeSpent / timer.scale);
const totalTime = totalTimeSpent / timer.scale; // Convert ns to seconds
const opsSec = totalIterations / totalTime;

const sampleData = histogram.samples;

Expand Down
Loading