Docs
Acton standard libraryTesting

bench

bench.tolk standard library file

Utilities for measuring and profiling Tolk callbacks in tests.

Definitions

bench

struct bench

Root namespace for benchmark helpers.

Source code

BenchInstructionInfo

struct BenchInstructionInfo {
    /// Row id in the profile map.
    id: uint32
    /// TVM instruction mnemonic, for example `LDI`, `CALLDICT`, or `implicit RET`.
    name: string
    /// Number of times this instruction mnemonic was executed.
    count: uint32
    /// Sum of gas used by all executions of this instruction mnemonic.
    totalGas: uint64
    /// Minimum gas used by one execution of this instruction mnemonic.
    minGas: uint64
    /// Maximum gas used by one execution of this instruction mnemonic.
    maxGas: uint64
}

Aggregated gas statistics for a single TVM instruction mnemonic executed by the measured callback.

The profiler groups samples by instruction mnemonic. For example, all LDI executions are merged into one BenchInstructionInfo row with the total number of executions and min/max gas observed for that mnemonic.

Source code

BenchResult

struct BenchResult<Ret> {
    /// Benchmark name passed as the first argument to `bench.measure`.
    name: string
    /// Callback return value deserialized as `Ret`.
    result: Ret
    /// Total gas attributed to the callback body.
    gasUsed: uint64
    /// Per-instruction gas profile keyed by row id.
    instructions: map<uint32, BenchInstructionInfo>
    /// TASM code of the measured callback body.
    asmCode: string
}

Result of bench.measure.

Example:

val profile = bench.measure("sum loop", fun() {
    return calculateSum();
});
println(bench.format(profile));
println(profile.asmCode);
Source code

bench.measure

fun bench.measure<Ret>(
    name: string,
    fn: () -> Ret,
    location: string = reflect.sourceLocationAsString(),
): BenchResult<Ret>

Measures a zero-argument callback and returns its result, total gas, per-instruction gas statistics, and the callback body TASM code.

Use a short descriptive name; it appears in formatted profile and diff output. Close over data in the surrounding test when you need inputs.

location is filled automatically and is used in failure messages.

Example:

get fun `test bench parser`() {
    val source = buildTestSlice();
    val profile = bench.measure("fromSlice", fun() {
        return Foo.fromSlice(source);
    });
    expect(profile.result.a).toEqual(1);
    println(bench.format(profile));
}
Source code

bench.format

fun bench.format<Ret>(profile: BenchResult<Ret>): string

Formats a table with per-instruction statistics for one measured profile.

The table includes total gas, average gas, min/max gas, and execution count for each instruction mnemonic.

Example:

val profile = bench.measure("sum loop", fun() {
    return calculateSum();
});
println(bench.format(profile));
Source code

bench.formatDiff

fun bench.formatDiff<BaselineRet, CurrentRet>(
    baseline: BenchResult<BaselineRet>,
    current: BenchResult<CurrentRet>,
): string

Formats a diff table. The first profile is the baseline, the second is current.

Use this when comparing two implementations of the same behavior. Positive gas diff means the current profile is more expensive; negative diff means it is cheaper.

Example:

val baseline = bench.measure("fromSlice", fun() {
    return Foo.fromSlice(source);
});
val current = bench.measure("manual parsing", fun() {
    return parseFooManually(source);
});
println(bench.formatDiff(baseline, current));
Source code

Last updated on

On this page