Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: evanwashere/mitata
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 5331e95d027b5dd364348358ba22a351c8d973e2
Choose a base ref
...
head repository: evanwashere/mitata
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: c0db24e47ac6223fe5dfa3968468f91751faaebc
Choose a head ref
  • 1 commit
  • 5 files changed
  • 1 contributor

Commits on Feb 4, 2025

  1. 1.0.34

    - add manual benchmarks
    - allow providing custom print function
    - include style information
    evanwashere committed Feb 4, 2025
    Copy the full SHA
    c0db24e View commit details
Showing with 115 additions and 46 deletions.
  1. +1 −1 package.json
  2. +1 −1 readme.md
  3. +23 −9 src/lib.mjs
  4. +29 −10 src/main.d.mts
  5. +61 −25 src/main.mjs
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
"name": "mitata",
"type": "module",
"license": "MIT",
"version": "1.0.33",
"version": "1.0.34",
"main": "src/main.mjs",
"types": "src/main.d.mts",
"files": ["src", "license", "readme.md"],
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
@@ -135,7 +135,7 @@ Array.from(512) 1.29 µs/iter 1.30 µs ▂▆█

## universal compatibility

Out of box mitata can detect engine/runtime it's running on and fall back to using [alternative](https://github.com/evanwashere/mitata/blob/master/src/lib.mjs#L45) non-standard I/O functions. If your engine or runtime is missing support, open an issue or pr requesting for support.
Out of box mitata can detect engine/runtime it's running on and fall back to using [alternative](https://github.com/evanwashere/mitata/blob/master/src/lib.mjs#L51) non-standard I/O functions. If your engine or runtime is missing support, open an issue or pr requesting for support.

### how to use mitata with engine CLIs like d8, jsc, graaljs, spidermonkey

32 changes: 23 additions & 9 deletions src/lib.mjs
Original file line number Diff line number Diff line change
@@ -20,20 +20,26 @@ export async function generator(gen, opts = {}) {
const g = gen(ctx);
const n = await g.next();

if (n.done || 'fn' !== kind(n.value)) {
if ('fn' !== kind(n.value?.bench, true)) throw new TypeError('expected benchmarkable yield from generator');
let $fn = n.value;
if (!n.value?.heap && null != n.value?.heap) opts.heap = false;
opts.concurrency ??= n.value?.concurrency ?? opts.args?.concurrency;
if (!n.value?.counters && null != n.value?.counters) opts.$counters = false;

if (n.done || 'fn' !== kind($fn)) {
$fn = n.value?.bench || n.value?.manual;
if ('fn' !== kind($fn, true)) throw new TypeError('expected benchmarkable yield from generator');

opts.params ??= {};
const params = n.value.bench.length;
const params = $fn.length;
opts.manual = !n.value.manual ? false : ('manual' !== n.value.budget ? 'real' : 'manual');

for (let o = 0; o < params; o++) {
opts.params[o] = n.value[o];
if ('fn' !== kind(n.value[o])) throw new TypeError('expected function for benchmark parameter');
}
}

opts.concurrency ??= n.value?.concurrency ?? opts.args?.concurrency;
const stats = await fn('fn' === kind(n.value) ? n.value : n.value.bench, opts);
const stats = await fn($fn, opts);
if (!(await g.next()).done) throw new TypeError('expected generator to yield once');

return {
@@ -133,6 +139,7 @@ function defaults(opts) {
opts.now ??= now;
opts.heap ??= null;
opts.params ??= {};
opts.manual ??= false;
opts.inner_gc ??= false;
opts.$counters ??= false;
opts.concurrency ??= k_concurrency;
@@ -180,6 +187,11 @@ export async function fn(fn, opts = {}) {
}
}

if (opts.manual) {
batch = false;
opts.concurrency = 1;
}

const loop = new AsyncFunction('$fn', '$gc', '$now', '$heap', '$params', '$counters', `
${!opts.$counters ? '' : 'let _hc = false;'}
${!opts.$counters ? '' : 'try { $counters.init(); _hc = true; } catch {}'}
@@ -225,27 +237,28 @@ export async function fn(fn, opts = {}) {
}
`}
${!opts.manual ? '' : 'let t2 = 0;'}
${!opts.heap ? '' : 'const h0 = $heap();'}
${!opts.$counters ? '' : 'if (_hc) try { $counters.before(); } catch {};'} const t0 = $now();
${!batch ? `
${!async ? '' : (1 >= opts.concurrency ? '' : 'await Promise.all([')}
${Array.from({ length: opts.concurrency }, (_, c) => `
${!async ? '' : (1 < opts.concurrency ? '' : 'await ')} ${(!params.length ? `
${!opts.manual ? '' : 't2 +='} ${!async ? '' : (1 < opts.concurrency ? '' : 'await')} ${(!params.length ? `
$fn()
` : `
$fn(${Array.from({ length: params.length }, (_, o) => `param_${o}_${c}`).join(', ')})
`).trim()}${!async ? ';' : (1 < opts.concurrency ? ',' : ';')}
`.trim()).join('\n')}
${!async ? '' : (1 >= opts.concurrency ? '' : ']);')}
${!async ? '' : (1 >= opts.concurrency ? '' : `]);`)}
` : `
for (let o = 0; o < ${(opts.batch_samples / opts.batch_unroll) | 0}; o++) {
${!params.length ? '' : `const param_offset = o * ${opts.batch_unroll};`}
${Array.from({ length: opts.batch_unroll }, (_, u) => `
${!async ? '' : (1 >= opts.concurrency ? '' : 'await Promise.all([')}
${Array.from({ length: opts.concurrency }, (_, c) => `
${!async ? '' : (1 < opts.concurrency ? '' : 'await ')} ${(!params.length ? `
${!async ? '' : (1 < opts.concurrency ? '' : 'await')} ${(!params.length ? `
$fn()
` : `
$fn(${Array.from({ length: params.length }, (_, o) => `param_${o}_${c}[${u === 0 ? '' : `${u} + `}param_offset]`).join(', ')})
@@ -285,7 +298,8 @@ export async function fn(fn, opts = {}) {
}
`};
const diff = t1 - t0; t += diff;
const diff = ${opts.manual ? 't2' : 't1 - t0'};
t += ${'manual' === opts.manual ? 't2' : 't1 - t0'};
samples[_] = diff ${!batch ? '' : `/ ${opts.batch_samples}`};
}
39 changes: 29 additions & 10 deletions src/main.d.mts
Original file line number Diff line number Diff line change
@@ -88,22 +88,28 @@ export function boxplot(f: () => Promise<any>): Promise<void>;
export function barplot(f: () => Promise<any>): Promise<void>;
export function group(name: string, f: () => Promise<any>): Promise<void>;

export function run(opts?: { throw?: boolean; filter?: RegExp; colors?: boolean; format?: 'json' | 'quiet' | 'mitata' | 'markdown' | { mitata: { name?: number | 'fixed' | 'longest' } }; }): Promise<{ context: ctx, benchmarks: trial[] }>;
export function run(opts?: {
throw?: boolean;
filter?: RegExp;
colors?: boolean;
print?: (s: string) => any;
observe?: (t: trial) => trial;

format?:
'json'
| 'quiet'
| 'mitata'
| 'markdown'
| { json: { debug?: boolean, samples?: boolean } }
| { mitata: { name?: number | 'fixed' | 'longest' } }
}): Promise<{ context: ctx, benchmarks: trial[] }>;

export const flags: {
compact: number;
baseline: number;
};

interface trial {
runs: run[];
alias: string;
baseline: boolean;
args: Record<string, any[]>;
kind: 'args' | 'static' | 'multi-args';
}

type run = ({
type Run = ({
stats: stats;
error: undefined;
} | {
@@ -114,6 +120,19 @@ type run = ({
args: Record<string, any>;
}

interface trial {
runs: Run[];
alias: string;
baseline: boolean;
args: Record<string, any[]>;
kind: 'args' | 'static' | 'multi-args';

style: {
compact: boolean;
highlight: false | string;
};
}

export class B {
constructor(name: string, fn: () => any);
constructor(name: string, gen: (state: k_state) => Gen);
Loading