Documentation
¶
Overview ¶
Package benchmark is a pure-Go (no cgo) reimplementation of the deterministic, interpreter-independent core of Ruby's standard-library Benchmark module (MRI 4.0.5 / benchmark 0.5.0): the Tms measurement value type, its memberwise arithmetic and %-directive formatting, and the report layout (caption, label justification, the bm/bmbm tables) — all expressed as pure functions over Tms values.
The only impure ingredient, the clock, is injected. MRI's Benchmark.measure reads Process.times (user/system CPU, plus children's) and a monotonic real clock; here a Clock seam supplies those numbers, so the host (go-embedded-ruby) wires in the real process clock while tests feed a fixed one for byte-for-byte deterministic output.
Index ¶
- Constants
- func MsWith(clock Clock, fn func()) float64
- func RealtimeWith(clock Clock, fn func()) float64
- func RehearsalFooter(width int, total Tms) string
- func RehearsalHeader(width int) string
- func TakeCaption(width int) string
- type Clock
- type Job
- type Report
- type Tms
- func Benchmark(clock Clock, caption string, labelWidth int, format string, ...) (string, []Tms)
- func Bm(clock Clock, labelWidth int, extraLabels []string, ...) (string, []Tms)
- func Bmbm(clock Clock, job *Job) (string, []Tms)
- func MeasureWith(clock Clock, label string, fn func()) Tms
- func NewTms(utime, stime, cutime, cstime, real float64, label string) Tms
- func (t Tms) Add(other Tms) Tms
- func (t Tms) AddScalar(x float64) Tms
- func (t Tms) AddWith(clock Clock, fn func()) Tms
- func (t Tms) Cstime() float64
- func (t Tms) Cutime() float64
- func (t Tms) Div(other Tms) Tms
- func (t Tms) DivScalar(x float64) Tms
- func (t Tms) Format(format string, args ...any) string
- func (t Tms) Label() string
- func (t Tms) Mul(other Tms) Tms
- func (t Tms) MulScalar(x float64) Tms
- func (t Tms) Real() float64
- func (t Tms) Stime() float64
- func (t Tms) Sub(other Tms) Tms
- func (t Tms) SubScalar(x float64) Tms
- func (t Tms) ToA() []any
- func (t Tms) ToS() string
- func (t Tms) Total() float64
- func (t Tms) Utime() float64
Constants ¶
const BenchmarkVersion = "2002-04-25"
BenchmarkVersion mirrors Benchmark::BENCHMARK_VERSION.
const CAPTION = " user system total real\n"
CAPTION is the default heading printed above a column of times. It matches Benchmark::Tms::CAPTION (and Benchmark::CAPTION) exactly, trailing newline included.
const FORMAT = "%10.6u %10.6y %10.6t %10.6r\n"
FORMAT is the default per-line format string, matching Benchmark::Tms::FORMAT (and Benchmark::FORMAT). The %u/%y/%t/%r directives are the Benchmark extensions resolved by Tms.Format.
Variables ¶
This section is empty.
Functions ¶
func MsWith ¶
MsWith runs fn and returns the elapsed real time in milliseconds, mirroring Benchmark.ms with an injected clock.
func RealtimeWith ¶
RealtimeWith runs fn and returns the elapsed real time in seconds, mirroring Benchmark.realtime with an injected clock.
func RehearsalFooter ¶
RehearsalFooter returns the bmbm rehearsal total line, matching " #{ets}\n\n".rjust(width+CAPTION.length+2, '-') where ets is the summed Tms formatted with "total: %tsec".
func RehearsalHeader ¶
RehearsalHeader returns the bmbm rehearsal banner line, matching 'Rehearsal '.ljust(width+CAPTION.length, '-'), where width is the bmbm label offset (job width + 1).
func TakeCaption ¶
TakeCaption returns the bmbm "take" (real run) caption line, matching ' '*width + CAPTION.
Types ¶
type Clock ¶
type Clock interface {
// Times returns the cumulative user, system, children's-user and
// children's-system CPU seconds, like Process.times.
Times() (utime, stime, cutime, cstime float64)
// Monotonic returns a monotonically increasing real-time reading in
// seconds, like Process.clock_gettime(Process::CLOCK_MONOTONIC).
Monotonic() float64
}
Clock is the injected time source for MeasureWith. It abstracts the two clocks MRI's Benchmark.measure reads: Process.times (the four CPU times) and a monotonic real clock (Process.clock_gettime(CLOCK_MONOTONIC)).
The host (go-embedded-ruby) supplies a Clock backed by the real process clock; tests supply a fixed or scripted Clock so the formatted output is fully deterministic.
type Job ¶
type Job struct {
// contains filtered or unexported fields
}
Job is one labelled block awaiting measurement, as collected by Bmbm. It mirrors Benchmark::Job's (label, block) pairs and tracks the widest label.
func NewJob ¶
NewJob returns a Job with the given initial label-offset width, mirroring Benchmark::Job.new(width).
type Report ¶
type Report struct {
// contains filtered or unexported fields
}
Report accumulates the measurements taken inside a bm/benchmark block and renders the table. It mirrors Benchmark::Report: a label offset (width) and a per-line format, growing the offset to fit the widest label, with the same off-by-one as MRI (the caller adds one to label_width before constructing it).
func NewReport ¶
NewReport returns a Report with the given label offset and per-line format, timing its blocks with clock. An empty format selects FORMAT, matching Benchmark::Report.new(width, format) where a nil format defers to Tms#format's default.
func (*Report) Caption ¶
Caption returns the heading line for the report: width leading spaces followed by CAPTION, exactly as Benchmark#benchmark prints it (" "*report.width + caption).
func (*Report) ExtraLine ¶
ExtraLine renders a trailing summary row built from a Tms the block returned (e.g. a total or average). label overrides the Tms label when non-empty, matching `(labels.shift || t.label || "").ljust(label_width)` in Benchmark#benchmark; labelWidth is the original label_width+1 offset.
func (*Report) Line ¶
Line renders one report row for t: the label left-justified to the report offset, then the formatted time columns. This is the pure rendering MRI does in Benchmark#benchmark's per-item loop.
type Tms ¶
type Tms struct {
// contains filtered or unexported fields
}
Tms holds the times associated with one benchmark measurement, mirroring Benchmark::Tms: user CPU time, system CPU time, the children's user and system CPU times, the elapsed real time, and a label. Total is the sum of the four CPU times.
func Benchmark ¶
func Benchmark(clock Clock, caption string, labelWidth int, format string, extraLabels []string, build func(report *Report) []Tms) (string, []Tms)
Benchmark is the general driver behind Bm: it prints caption, runs each block registered through the report builder, and appends summary lines built from the Tms slice the builder returns. It mirrors Benchmark.benchmark, returning the rendered table and the collected measurements.
labelWidth and the per-line format match the Ruby parameters; the report's effective offset is labelWidth+1 (MRI's `label_width += 1`). build receives a *Report whose Record both times (via clock) and renders each row, and may return extra Tms summary rows; extraLabels override their labels in order.
func Bm ¶
func Bm(clock Clock, labelWidth int, extraLabels []string, build func(report *Report) []Tms) (string, []Tms)
Bm renders the simple bm table: CAPTION on top, one timed line per report item, with labels left-justified to labelWidth. extraLabels label any summary Tms the builder returns. It mirrors Benchmark.bm.
func Bmbm ¶
Bmbm renders the rehearsal-then-real bmbm report and returns the rendered text plus the real-run measurements. It mirrors Benchmark.bmbm: it computes the label width from the registered jobs (job width + 1), prints the rehearsal banner, a rehearsal line per job, the rehearsal total footer, then the take caption and a real line per job.
Each block is measured twice with the injected clock (rehearsal then take), so a scripted clock makes the whole report deterministic.
func MeasureWith ¶
MeasureWith runs fn and returns a Tms holding the CPU and real time it took, labelled label. It mirrors Benchmark.measure: it samples the clock before and after fn and takes memberwise differences. The clock is injected via clock.
func NewTms ¶
NewTms returns a Tms with the given times and label. As in MRI, total is computed as utime+stime+cutime+cstime and a nil-equivalent (empty) label is stored verbatim (MRI calls label.to_s, so nil becomes "").
func (Tms) Add ¶
Add returns a new Tms whose times are the memberwise sum of t and other, matching Tms#+. The result label is empty, exactly as MRI's memberwise leaves it.
func (Tms) AddScalar ¶
AddScalar returns a new Tms with x added to every time, matching Tms#+ with a numeric operand (MRI applies the scalar to all five fields, real included).
func (Tms) AddWith ¶
AddWith returns the memberwise sum of t and a fresh measurement of fn, mirroring Tms#add. The block is timed with the injected clock.
func (Tms) Format ¶
Format renders t according to format, honouring the Benchmark extensions on top of standard %-directives, matching Tms#format byte-for-byte:
%n label %u utime %y stime (system) %U cutime %t total %r real (wrapped in parentheses) %Y cstime
The flag/width/precision run before the extension letter is preserved (e.g. %10.6u). An empty format selects FORMAT, in which case the trailing args are ignored (as MRI does when format is nil). With an explicit format, any remaining standard directives are filled from args.
func (Tms) ToA ¶
ToA returns the 6-element slice [label, utime, stime, cutime, cstime, real], mirroring Tms#to_a.
