@thi.ng/bench
Version:
Benchmarking & profiling utilities w/ various statistics & formatters (CSV, JSON, Markdown etc.)
233 lines • 6.91 kB
TypeScript
import type { FnAny, IDeref, IEnable, IObjectOf, IReset } from "@thi.ng/api";
import type { Timestamp } from "./api.js";
export interface Profile {
t0: Timestamp[];
total: Timestamp;
calls: number;
maxDepth: number;
}
export interface ProfileResult {
/**
* User provided profile name/ID
*/
id: string;
/**
* Number of calls recorded
*/
calls: number;
/**
* Total number of milliseconds consumed by this profile (minus internal
* computed overhead)
*/
total: number;
/**
* Mean number of milliseconds per call (aka `total / calls`)
*/
timePerCall: number;
/**
* Percentage of this profile's time contribution to the profiled grand
* total (the grand total is _not_ wall clock time, but the sum of all
* profiles).
*/
totalPercent: number;
/**
* Percentage of this profile's number of calls out of the profiled grand total.
*/
callsPercent: number;
/**
* Max recorded recursion depth. See {@link Profiler.start} for example.
*/
maxDepth: number;
}
export interface ProfilerOpts {
/**
* Number of warmup iterations to compute the profiler's internal overhead.
*
* @defaultValue 1_000_000
*/
warmup: number;
/**
* Unless set to false, the profiler will be enabled by default.
*
* @defaultValue true
*/
enabled: boolean;
}
export declare class Profiler implements IDeref<IObjectOf<ProfileResult>>, IEnable<Profiler>, IReset {
protected _session: Profile | undefined;
protected _profiles: IObjectOf<Profile>;
protected _enabled: boolean;
protected _overhead: number;
constructor(opts?: Partial<ProfilerOpts>);
isEnabled(): boolean;
/**
* Disables profiler and clears all existing profiles.
*
* @remarks
* Calls to {@link Profiler.start} and {@link Profiler.end} only are no-ops
* if the profiler is currently disabled.
*/
disable(): void;
/**
* Enables profiler and clears all existing profiles.
*
* @remarks
* Calls to {@link Profiler.start} and {@link Profiler.end} only are no-ops
* if the profiler is currently disabled.
*/
enable(): void;
/**
* Resets profiler state and clears all recorded profiles.
*/
reset(): this;
/**
* Prepare and return all recorded profiles as object of
* {@link ProfileResult}s.
*
* @remarks
* Automatically computes and subtracts internal overhead from each
* profile's total (Overhead is computed during profiler ctor and/or
* {@link Profiler.warmup}).
*
* Also see {@link Profiler.asCSV} to obtain results in CSV format.
*/
deref(): IObjectOf<ProfileResult>;
/**
* Start a new profile (or add to an existing ID) by recording current
* timestamp (via {@link now}), number of calls (to this method and for this
* ID), as well as max. recursion depth. Use {@link Profiler.end} to
* stop/update measurements.
*
* @remarks
* Profiling only happens if the profiler is currently enabled, else a
* no-op.
*
* * @example
* ```ts tangle:../export/profiler.ts
* import { Profiler } from "@thi.ng/bench";
*
* const profiler = new Profiler();
*
* // recursive function
* const countdown = (n: number, acc: number[] = []) => {
* profiler.start("countdown");
* if (n > 0) countdown(n - 1, (acc.push(n),acc));
* profiler.end("countdown");
* return acc;
* }
*
* console.log(countdown(10));
* // [ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ]
*
* console.log(countdown(5));
* // [ 5, 4, 3, 2, 1 ]
*
* console.log(profiler.deref());
* // {
* // countdown: {
* // id: 'countdown',
* // total: 0.029665688286,
* // timePerCall: 0.0017450404874117648,
* // totalPercent: 96.0872831622525,
* // calls: 17,
* // callsPercent: 100,
* // maxDepth: 11
* // }
* // }
* ```
*
* @param id
*/
start(id: string): void;
/**
* Ends/updates measurements for given profile ID. Throws error if `id` is
* invalid or if no active profiling iteration exists for this ID (e.g. if
* this method is called more often than a corresponding
* {@link Profiler.start}).
*
* @remarks
* Profiling only happens if the profiler is currently enabled, else a
* no-op.
*
* @param id
*/
end(id: string): void;
/**
* Takes a profile `id`, function `fn` and any (optional) arguments. Calls
* `fn` with given args and profiles it using provided ID. Returns result
* of `fn`.
*
* @remarks
* Also see {@link Profiler.wrap}
*
* @param id
* @param fn
*/
profile<T>(id: string, fn: FnAny<T>, ...args: any[]): T;
/**
* Higher-order version of {@link Profiler.profile}. Takes a profile `id`
* and vararg function `fn`. Returns new function which when called, calls
* given `fn` and profiles it using provided `id`, then returns result of
* `fn`.
*
* @example
* ```ts tangle:../export/profiler-wrap.ts
* import { Profiler } from "@thi.ng/bench";
*
* const profiler = new Profiler();
*
* const sum = profiler.wrap(
* "sum",
* (vec: number[]) => vec.reduce((acc, x) => acc + x, 0)
* );
*
* console.log(sum([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]));
* // 55
*
* console.log(profiler.deref());
* // {
* // sum: {
* // id: 'sum',
* // total: 0.015644915291,
* // timePerCall: 0.015644915291,
* // totalPercent: 100,
* // calls: 1,
* // callsPercent: 100,
* // maxDepth: 1
* // }
* // }
* ```
*
* @param id
* @param fn
*/
wrap<T>(id: string, fn: FnAny<T>): (...args: any[]) => T;
/**
* Estimates the internal overhead of the {@link Profiler.start} and
* {@link Profiler.end} methods by performing given number of `iter`ations
* (distributed over 10 runs) and taking the mean duration of those runs.
*
* @remarks
* The computed overhead (per iteration) will be subtracted from the all
* recorded profiles (see {@link Profiler.deref} and
* {@link Profiler.asCSV}).
*
* @param iter
*/
warmup(iter: number): void;
/**
* Same as {@link Profiler.deref}.
*/
toJSON(): IObjectOf<ProfileResult>;
/**
* Returns {@link Profiler.deref} formatted as CSV string.
*/
asCSV(): string;
protected newProfile(t0: Timestamp): {
t0: Timestamp[];
total: number | bigint;
calls: number;
maxDepth: number;
};
}
//# sourceMappingURL=profiler.d.ts.map