بنقرة واحدة
write-bench
// Write a benchmark file for nano-bench (comparing multiple functions). Use when asked to create a benchmark, compare implementations, or measure performance of code variants.
// Write a benchmark file for nano-bench (comparing multiple functions). Use when asked to create a benchmark, compare implementations, or measure performance of code variants.
| name | write-bench |
| description | Write a benchmark file for nano-bench (comparing multiple functions). Use when asked to create a benchmark, compare implementations, or measure performance of code variants. |
nano-bench compares multiple implementations of the same operation using nonparametric statistics and significance testing.
A benchmark file is an ESM module that default-exports an object of functions. Each function takes n (iteration count) and runs the measured code in a for loop of n iterations.
export default {
variantA: n => {
for (let i = 0; i < n; ++i) {
// code under test
}
},
variantB: n => {
for (let i = 0; i < n; ++i) {
// alternative implementation
}
}
};
export default { ... } — no CommonJS.n. The loop for (let i = 0; i < n; ++i) is mandatory — it amortizes function-call overhead, which is critical for micro-benchmarks.for loop (or at module scope) so setup cost is not measured.bench/bench-<descriptive-name>.js.If the JS engine might optimize away the result, keep it alive:
export default {
variantA: n => {
const x = [];
for (let i = 0; i < n; ++i) {
x.pop();
x.push(someComputation());
}
return x;
},
variantB: n => {
const x = [];
for (let i = 0; i < n; ++i) {
x.pop();
x.push(otherComputation());
}
return x;
}
};
Use the x.pop(); x.push(...) pattern to keep the array at length ≤ 1 while still preventing elimination.
Benchmark functions can be async. The tool detects thenables and measures time until resolution.
export default {
asyncVariantA: async n => {
for (let i = 0; i < n; ++i) {
await someAsyncWork();
}
},
asyncVariantB: async n => {
for (let i = 0; i < n; ++i) {
await otherAsyncWork();
}
}
};
Use --parallel (-p) when benchmarking async code to collect samples concurrently.
By default the tool uses the default export. To use a named export:
export const myBench = {
a: n => {
// ...
},
b: n => {
// ...
}
};
Run with: npx nano-bench -e myBench bench/bench-file.js
Code that should run once (not measured) goes at module scope:
const data = Array.from({length: 1000}, () => Math.random());
export default {
sort: n => {
for (let i = 0; i < n; ++i) {
data.slice().sort((a, b) => a - b);
}
},
sortReverse: n => {
for (let i = 0; i < n; ++i) {
data.slice().sort((a, b) => b - a);
}
}
};
npx nano-bench bench/bench-<name>.js
npx nano-bench -s 200 -b 2000 -a 0.01 bench/bench-<name>.js # more samples, tighter CI
npx nano-bench -i 10000 bench/bench-<name>.js # fixed iteration count
# Alternative runtimes
bun `npx nano-bench --self` bench/bench-<name>.js
deno run -A `npx nano-bench --self` bench/bench-<name>.js
const isPalindromeSlice = s => {
while (s.length > 1) {
if (s[0] !== s[s.length - 1]) break;
s = s.slice(1, -1);
}
return s.length <= 1;
};
const isPalindromeIndex = s => {
let l = 0,
r = s.length - 1;
while (l < r) {
if (s[l] !== s[r]) break;
++l;
--r;
}
return l >= r;
};
const sample = 'abcba'.repeat(40);
export default {
'using slice()': n => {
for (let i = 0; i < n; ++i) {
isPalindromeSlice(sample);
}
},
'using index': n => {
for (let i = 0; i < n; ++i) {
isPalindromeIndex(sample);
}
}
};
Write a benchmark file for nano-watch (continuous single-function monitoring). Use when asked to create a watch benchmark, monitor performance over time, or check for memory leaks.
Write or update tape-six tests for a module or feature. Use when asked to write tests, add test coverage, or create test files.