Skip to content

Commit

Permalink
sync
Browse files Browse the repository at this point in the history
  • Loading branch information
RafaelGSS committed Dec 15, 2024
1 parent d65e8aa commit 581af73
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 9 deletions.
11 changes: 11 additions & 0 deletions examples/worker-threads/node.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const { Suite } = require('../../lib');

const suite = new Suite({
useWorkers: true,
});

suite
.add('single with matcher', function () {
return require('node:fs');
})
.run();
7 changes: 1 addition & 6 deletions lib/clock.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,7 @@ const SyncFunction = function () {
}.constructor;

function createRunner(bench, recommendedCount) {
const isAsync = types.isAsyncFunction(bench.fn);
const hasArg = bench.fn.length >= 1;

if (bench.fn.length > 1) {
process.emitWarning(`The benchmark "${ bench.name }" function should not have more than 1 argument.`);
}
const { isAsync, hasArg } = bench;

const compiledFnStringFactory = hasArg ? createRunManagedBenchmark : createRunUnmanagedBenchmark;
const compiledFnString = compiledFnStringFactory(bench, isAsync ? 'await ' : '');
Expand Down
45 changes: 44 additions & 1 deletion lib/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
const Piscina = require('piscina');
const { types } = require('node:util');

const { textReport, chartReport, htmlReport } = require('./report');
const { getInitialIterations, runBenchmark, runWarmup } = require('./lifecycle');
const { debugBench, timer } = require('./clock');
Expand All @@ -15,6 +18,11 @@ const {
validateArray,
} = require('./validators');

const getFunctionBody = (string) => string.substring(
string.indexOf("{") + 1,
string.lastIndexOf("}")
);

class Benchmark {
name = 'Benchmark';
fn;
Expand All @@ -30,6 +38,20 @@ class Benchmark {
this.maxTime = maxTime;
this.plugins = plugins;
this.repeatSuite = repeatSuite;

this.hasArg = this.fn.length >= 1;
if (this.fn.length > 1) {
process.emitWarning(`The benchmark "${ this.name }" function should not have more than 1 argument.`);
}

this.isAsync = types.isAsyncFunction(this.fn);
}

serializeBenchmark() {
// Regular functions can't be passed to worker.postMessage
// So we pass the string and deserialize it into a new Function
// on worker
this.fn = getFunctionBody(this.fn.toString());
}
}

Expand All @@ -52,6 +74,8 @@ class Suite {
#benchmarks;
#reporter;
#plugins;
#useWorkers;
#workerPool;

constructor(options = {}) {
this.#benchmarks = [];
Expand All @@ -65,6 +89,13 @@ class Suite {
this.#reporter = textReport;
}

this.#useWorkers = options.useWorkers || false;
if (this.#useWorkers) {
this.#workerPool = new Piscina({
filename: require.resolve('./worker-runner'),
});
}

if (options?.plugins) {
validateArray(options.plugins, 'plugin');
validatePlugins(options.plugins);
Expand Down Expand Up @@ -118,13 +149,25 @@ class Suite {
// Warmup is calculated to reduce noise/bias on the results
const initialIteration = await getInitialIterations(benchmark);
debugBench(`Starting ${ benchmark.name } with minTime=${ benchmark.minTime }, maxTime=${ benchmark.maxTime }, repeatSuite=${ benchmark.repeatSuite }`);
const result = await runBenchmark(benchmark, initialIteration, benchmark.repeatSuite);

let result;
if (this.#useWorkers) {
benchmark.serializeBenchmark();
result = await this.#workerPool.run({
benchmark,
initialIteration,
repeatSuite: benchmark.repeatSuite,
});
} else {
result = await runBenchmark(benchmark, initialIteration, benchmark.repeatSuite);
}
results[i] = result;
}

if (this.#reporter) {
this.#reporter(results);
}
// TODO: should destroy workerPool?

return results;
}
Expand Down
1 change: 0 additions & 1 deletion lib/lifecycle.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ async function runBenchmark(bench, initialIterations, repeatSuite) {
histogram,
{ initialIterations, maxDuration, minSamples }
);

totalTimeSpent += timeSpent;
totalIterations += iterations;
}
Expand Down
17 changes: 17 additions & 0 deletions lib/worker-runner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use strict';

const { runBenchmark } = require('./lifecycle');

function deserializeBenchmark(benchmark) {
// TODO: isAsync
benchmark.fn = new Function(benchmark.fn);
}

module.exports = async function runWorkerBenchmark({ benchmark, iterations, repeatSuite }) {
console.log('Before deserialize:', benchmark)
deserializeBenchmark(benchmark);
console.log('After deserialize:', benchmark)
const result = await runBenchmark(benchmark, iterations, repeatSuite);
console.log('Result', result)
return result;
};
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,8 @@
"bugs": {
"url": "https://github.com/RafaelGSS/bench-node/issues"
},
"homepage": "https://github.com/RafaelGSS/bench-node#readme"
"homepage": "https://github.com/RafaelGSS/bench-node#readme",
"dependencies": {
"piscina": "^4.8.0"
}
}

0 comments on commit 581af73

Please sign in to comment.