iso-bench
Advanced tools
Comparing version 2.4.5 to 2.4.6
import { IsoBenchOptions, Processor } from "."; | ||
import { SetupMessage } from "./WorkerSetup"; | ||
export declare type RunMessage = { | ||
error: string; | ||
} | { | ||
diff: number; | ||
cycles: number; | ||
warmUpCycles: number; | ||
}; | ||
export declare type Sample = { | ||
@@ -21,4 +14,2 @@ cycles: number; | ||
error: string | null; | ||
cycles: number; | ||
warmUpCycles: number; | ||
opMs: number; | ||
@@ -30,9 +21,5 @@ totalTime: number; | ||
fork(benchName: string, processors: Processor[], options: Required<IsoBenchOptions>): Promise<void>; | ||
run(setup: SetupMessage): { | ||
diff: number; | ||
cycles: number; | ||
warmUpCycles: number; | ||
}; | ||
run(setup: SetupMessage): Promise<void>; | ||
private _getResult; | ||
private _getCallbackTime; | ||
} |
export declare type SetupMessage = { | ||
testI: number; | ||
testIndex: number; | ||
benchName: string; | ||
cycles: number; | ||
warmUpCycles: number; | ||
time: number; | ||
samples: number; | ||
warmUpTime: number; | ||
}; | ||
export declare let WorkerSetup: SetupMessage | null; |
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.IsoBench = void 0; | ||
const fs_1 = __importDefault(require("fs")); | ||
const Test_1 = require("./Test"); | ||
const Messager_1 = require("./Messager"); | ||
const WorkerSetup_1 = require("./WorkerSetup"); | ||
@@ -31,5 +28,5 @@ const processors_1 = require("./processors"); | ||
parallel: 1, | ||
samples: 1, | ||
time: 3000, | ||
warmUpTime: 500 | ||
samples: 100, | ||
time: 50, | ||
warmUpTime: 50 | ||
}, ...options }; | ||
@@ -116,21 +113,20 @@ this.name = getUniqueName(this.name, BENCHES); | ||
} | ||
_start(setup) { | ||
async _start(setup) { | ||
if (this.name === setup.benchName) { | ||
let sendData; | ||
try { | ||
const test = this.tests[setup.testI]; | ||
const test = this.tests[setup.testIndex]; | ||
if (!test) { | ||
throw new Error("Test index " + setup.testI + " not found"); | ||
throw new Error("Test index " + setup.testIndex + " not found"); | ||
} | ||
sendData = test.run(setup); | ||
await test.run(setup); | ||
await Messager_1.Messager.send({ | ||
done: true | ||
}); | ||
} | ||
catch (e) { | ||
sendData = { | ||
await Messager_1.Messager.send({ | ||
error: String(e) | ||
}; | ||
}); | ||
} | ||
const bufferLength = Buffer.allocUnsafe(2); | ||
const buffer = Buffer.from(JSON.stringify(sendData)); | ||
bufferLength.writeUint16LE(buffer.length); | ||
fs_1.default.createWriteStream("", { fd: 3 }).write(Buffer.concat([bufferLength, buffer]), () => process.exit()); | ||
setTimeout(() => process.exit(), 100); | ||
} | ||
@@ -137,0 +133,0 @@ } |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Test = void 0; | ||
const perf_hooks_1 = require("perf_hooks"); | ||
const Fork_1 = require("./Fork"); | ||
const Messager_1 = require("./Messager"); | ||
class ForkContext { | ||
@@ -21,6 +23,5 @@ _test; | ||
const setup = { | ||
testI: this._test.index, | ||
testIndex: this._test.index, | ||
benchName: this._benchName, | ||
cycles: this._test.cycles, | ||
warmUpCycles: this._test.warmUpCycles, | ||
samples: this._options.samples, | ||
time: this._options.time, | ||
@@ -35,24 +36,22 @@ warmUpTime: this._options.warmUpTime | ||
} | ||
_done(error, diff, cycles, warmUpCycles) { | ||
_processMessage(msg) { | ||
if (!this._ended) { | ||
this._ended = true; | ||
if (cycles) { | ||
this._test.cycles = cycles; | ||
} | ||
if (warmUpCycles) { | ||
this._test.warmUpCycles = warmUpCycles; | ||
} | ||
if (error) { | ||
if (msg.error != null) { | ||
this._test.opMs = 0; | ||
this._test.error = error; | ||
this._test.error = msg.error; | ||
this._ended = true; | ||
this._resolve(); | ||
} | ||
else if (diff) { | ||
else if (msg.done) { | ||
this._ended = true; | ||
this._resolve(); | ||
} | ||
else { | ||
const sample = { | ||
cycles: this._test.cycles, | ||
time: diff, | ||
ops: this._test.cycles / diff | ||
cycles: msg.cycles, | ||
time: msg.diff, | ||
ops: msg.cycles / msg.diff | ||
}; | ||
this._test.samples.push(sample); | ||
this._test.totalTime += diff; | ||
this._test.totalTime += msg.diff; | ||
this._test.opMs = this._test.samples.reduce((total, sample) => total + sample.ops, 0) / this._test.samples.length; | ||
@@ -62,8 +61,2 @@ for (const processor of this._processors) { | ||
} | ||
if (this._test.samples.length >= this._options.samples) { | ||
this._resolve(); | ||
} | ||
else { | ||
new ForkContext(this._test, this._processors, this._resolve, this._benchName, this._options).start(); | ||
} | ||
} | ||
@@ -77,3 +70,6 @@ } | ||
while (stream.readable) { | ||
if (size == null) { | ||
if (this._ended) { | ||
break; | ||
} | ||
else if (size == null) { | ||
const buffer = stream.read(2); | ||
@@ -90,11 +86,6 @@ if (buffer && buffer.length === 2) { | ||
if (buffer && buffer.length === size) { | ||
size = null; | ||
const message = JSON.parse(String(buffer)); | ||
if ("error" in message) { | ||
this._done(message.error); | ||
} | ||
else { | ||
this._done("", message.diff, message.cycles, message.warmUpCycles); | ||
} | ||
this._processMessage(message); | ||
} | ||
break; | ||
} | ||
@@ -104,3 +95,5 @@ } | ||
catch (e) { | ||
this._done(String(e)); | ||
this._processMessage({ | ||
error: String(e) | ||
}); | ||
} | ||
@@ -117,3 +110,5 @@ }); | ||
} | ||
this._done(err); | ||
this._processMessage({ | ||
error: err | ||
}); | ||
}); | ||
@@ -128,4 +123,2 @@ } | ||
error = null; | ||
cycles = 1; | ||
warmUpCycles = 1; | ||
opMs = 0; | ||
@@ -147,15 +140,18 @@ totalTime = 0; | ||
} | ||
run(setup) { | ||
const warmUpResult = setup.warmUpTime > 0 ? this._getResult(setup.warmUpTime, setup.warmUpCycles) : null; | ||
if (warmUpResult && warmUpResult.cycles !== setup.warmUpCycles) { | ||
async run(setup) { | ||
const warmUpResult = setup.warmUpTime > 0 ? this._getResult(setup.warmUpTime, 1) : null; | ||
let cycles = 1; | ||
if (warmUpResult) { | ||
const ratio = (setup.time / setup.warmUpTime) * 1.02; | ||
setup.cycles = warmUpResult.cycles * ratio; | ||
cycles = warmUpResult.cycles * ratio; | ||
} | ||
const result = this._getResult(setup.time, setup.cycles); | ||
const runResult = { | ||
diff: result.diff, | ||
cycles: result.cycles, | ||
warmUpCycles: warmUpResult ? warmUpResult.cycles : 0 | ||
}; | ||
return runResult; | ||
let samples = setup.samples; | ||
while (samples-- > 0) { | ||
const result = this._getResult(setup.time, cycles); | ||
cycles = result.cycles; | ||
await Messager_1.Messager.send({ | ||
diff: result.diff, | ||
cycles: result.cycles | ||
}); | ||
} | ||
} | ||
@@ -179,14 +175,14 @@ _getResult(targetTime, cycles) { | ||
const setup = this._setup(); | ||
const startTS = process.hrtime.bigint(); | ||
const startTS = perf_hooks_1.performance.now(); | ||
while (cycles-- > 0) { | ||
this._callback(setup); | ||
} | ||
return Number(process.hrtime.bigint() - startTS) / 1000000; | ||
return perf_hooks_1.performance.now() - startTS; | ||
} | ||
else { | ||
const startTS = process.hrtime.bigint(); | ||
const startTS = perf_hooks_1.performance.now(); | ||
while (cycles-- > 0) { | ||
this._callback(); | ||
} | ||
return Number(process.hrtime.bigint() - startTS) / 1000000; | ||
return perf_hooks_1.performance.now() - startTS; | ||
} | ||
@@ -193,0 +189,0 @@ } |
{ | ||
"name": "iso-bench", | ||
"version": "2.4.5", | ||
"version": "2.4.6", | ||
"description": "Small benchmark library focused in avoiding optimization/deoptimization pollution between tests by isolating them.", | ||
@@ -5,0 +5,0 @@ "types": "./lib/_types/index.d.ts", |
@@ -127,4 +127,4 @@ # iso-bench | ||
- `parallel`: The amount of parallel tests to run. Defaults to **1**. | ||
- `time`: The minimum time (in milliseconds) to invest on each test. The library will automatically increase the amount of cycles to reach a minimum of `ms` between tests to take samples. Defaults to **3000**. | ||
- `samples`: Amount of samples to get. Defaults to **1**. | ||
- `time`: The minimum time (in milliseconds) to invest on each test. The library will automatically increase the amount of cycles to reach a minimum of `ms` between tests to take samples. Defaults to **50**. | ||
- `samples`: Amount of samples to get. Defaults to **100**. | ||
- `warmUpTime`: The minimum time (in milliseconds) to pre-run the tests, so the [JavaScript engine optimizer kicks-in](https://doar-e.github.io/blog/2019/01/28/introduction-to-turbofan/#compilation-pipeline:~:text=If%20the%20function%20gets%20executed%20a%20lot%2C%20TurboFan%20will%20generate%20some%20optimized%20code) before initializing the timer. Defaults to **500**. | ||
@@ -204,3 +204,3 @@ | ||
``` | ||
Adds a built-in [Processor](#i-processor) that outputs the result in a writable stream, like a file or a socket. The writable stream should be returned inside the callback function and will be only called in the main process. Returns the IsoBench instance. | ||
Adds a built-in [Processor](#i-processor) that outputs the result in a writable stream, like a file or a socket. The writable stream should be returned inside the callback function so it will be only called in the main process. Returns the IsoBench instance. | ||
@@ -211,3 +211,3 @@ --- | ||
``` | ||
Adds a custom [Processor](#i-processor) that must implement the [Processor](#i-processor) interface. The callback should return a [Processor](#i-processor) instance and will be only called in the main process. Returns the IsoBench instance. | ||
Adds a custom [Processor](#i-processor) that must implement the [Processor](#i-processor) interface. The callback should return a [Processor](#i-processor) instance so it will be only called in the main process. Returns the IsoBench instance. | ||
@@ -214,0 +214,0 @@ --- |
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
42689
32
935
3