UNPKG

@dapplion/benchmark

Version:

Ensures that new code does not introduce performance regressions with CI. Tracks:

150 lines (149 loc) 5.36 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.itBench = void 0; exports.setBenchOpts = setBenchOpts; const node_fs_1 = __importDefault(require("node:fs")); const node_path_1 = __importDefault(require("node:path")); const globalState_js_1 = require("./globalState.js"); const runBenchFn_js_1 = require("./runBenchFn.js"); const utils_js_1 = require("./utils.js"); const itBenchFn = function itBench(idOrOpts, fn) { // TODO: // Implement reporter // Implement grouping functionality // if (this.averageNs === null) this.averageNs = result.averageNs; // result.factor = result.averageNs / this.averageNs; let opts = coerceToOptsObj(idOrOpts, fn); // Apply mocha it opts const itFn = opts.only ? it.only : opts.skip ? it.skip : it; itFn(opts.id, async function () { const parent = (0, utils_js_1.getParentSuite)(this); const optsParent = getOptsFromParent(parent); // Get results array from root suite const rootSuite = (0, utils_js_1.getRootSuite)(parent); const results = globalState_js_1.resultsByRootSuite.get(rootSuite); const rootOpts = globalState_js_1.optsByRootSuite.get(rootSuite); if (!results || !rootOpts) throw Error("root suite not found"); opts = Object.assign({}, rootOpts, optsParent, opts); // Ensure bench id is unique if (results.has(opts.id)) { throw Error(`test titles must be unique, duplicated: '${opts.id}'`); } // Extend timeout if maxMs is set if (opts.timeoutBench !== undefined) { this.timeout(opts.timeoutBench); } else { const timeout = this.timeout(); if (opts.maxMs && opts.maxMs > timeout) { this.timeout(opts.maxMs * 1.5); } else if (opts.minMs && opts.minMs > timeout) { this.timeout(opts.minMs * 1.5); } } // Persist full results if requested. dir is created in `beforeAll` const benchmarkResultsCsvDir = process.env.BENCHMARK_RESULTS_CSV_DIR; const persistRunsNs = Boolean(benchmarkResultsCsvDir); const { result, runsNs } = await (0, runBenchFn_js_1.runBenchFn)(opts, persistRunsNs); // Store result for: // - to persist benchmark data latter // - to render with the custom reporter results.set(opts.id, result); if (benchmarkResultsCsvDir) { node_fs_1.default.mkdirSync(benchmarkResultsCsvDir, { recursive: true }); const filename = `${result.id}.csv`; const filepath = node_path_1.default.join(benchmarkResultsCsvDir, filename); node_fs_1.default.writeFileSync(filepath, runsNs.join("\n")); } }); }; exports.itBench = itBenchFn; exports.itBench.only = function itBench(idOrOpts, fn) { const opts = coerceToOptsObj(idOrOpts, fn); opts.only = true; itBenchFn(opts); }; exports.itBench.skip = function itBench(idOrOpts, fn) { const opts = coerceToOptsObj(idOrOpts, fn); opts.skip = true; itBenchFn(opts); }; function coerceToOptsObj(idOrOpts, fn) { let opts; if (typeof idOrOpts === "string") { if (!fn) throw Error("fn arg must be set"); opts = { id: idOrOpts, fn }; } else { if (fn) { opts = { ...idOrOpts, fn }; } else { const optsWithFn = idOrOpts; if (!optsWithFn.fn) throw Error("opts.fn arg must be set"); opts = optsWithFn; } } return opts; } /** * Customize benchmark opts for a describe block. Affects only tests within that Mocha.Suite * ```ts * describe("suite A1", function () { * setBenchOpts({runs: 100}); * // 100 runs * itBench("bench A1.1", function() {}); * itBench("bench A1.2", function() {}); * // 300 runs * itBench({id: "bench A1.3", runs: 300}, function() {}); * * // Supports nesting, child has priority over parent. * // Arrow functions can be used, won't break it. * describe("suite A2", () => { * setBenchOpts({runs: 200}); * // 200 runs. * itBench("bench A2.1", () => {}); * }) * }) * ``` */ function setBenchOpts(opts) { before(function () { if (this.currentTest?.parent) { globalState_js_1.optsMap.set(this.currentTest?.parent, opts); } }); after(function () { // Clean-up to allow garbage collection if (this.currentTest?.parent) { globalState_js_1.optsMap.delete(this.currentTest?.parent); } }); } function getOptsFromParent(parent) { const optsArr = []; getOptsFromSuite(parent, optsArr); // Merge opts, highest parent = lowest priority return Object.assign({}, ...optsArr.reverse()); } /** * Recursively append suite opts from child to parent. * * @returns `[suiteChildOpts, suiteParentOpts, suiteParentParentOpts]` */ function getOptsFromSuite(suite, optsArr) { const suiteOpts = globalState_js_1.optsMap.get(suite); if (suiteOpts) { optsArr.push(suiteOpts); } if (suite.parent) { getOptsFromSuite(suite.parent, optsArr); } }