Commit Graph

8 Commits

Author SHA1 Message Date
a4243bfcf6 simplify runner and simplify suite
runner.zig:
  - rename shadowed bytes_per_op to declared_bytes
  - inline trivial intermediates into the Result return block

suite.zig:
  - collapse verbose if/else in parse_duration_ns into a compact
    expression-style return
2026-05-23 10:23:51 +03:00
cdbdb9b351 refactor: simplify after code review
Aggregated fixes from a three-axis review (reuse, quality, efficiency):

- benchmark.zig: store raw bytes_per_op on Benchmark instead of pre-
  multiplying by b.n inside set_bytes. Reset no longer clobbers it, so
  the call order no longer matters and the math moves to result
  finalization where n is final.
- runner.zig: drop the runner-initiated b.reset_timer (was duplicative
  with the user's own reset_timer at the top of every bench). Pack
  counter/sub_run/sub_run_ctx/io into a runner.Env so run_one's
  signature stays at four params instead of seven.
- reporter.zig: remove the [256]f64 stack buffer that silently
  truncated --count=500. Reporters now take a pre-computed Summary and
  raw ns_samples slice from the suite. Replace the hand-rolled JSON
  string escape with std.json.Stringify.encodeJsonString.
- suite.zig: replace four nullable active_* fields with an explicit
  RunCtx threaded through run_named and the sub_run trampoline.
  Allocate ns_samples once per benchmark group. Extract match_flag for
  the eight identical --foo= prefix checks and open_stderr for the
  duplicated stderr-writer dance.

`--count=500` now produces 500 JSON samples (was 256 silently). No
behavior change for users at the API level beyond the set_bytes
ordering footgun being removed.
2026-05-21 08:33:24 +03:00
3f52ff1eeb docs: add README with usage examples
Covers setup (build.zig.zon + zbench_build helper), the minimal
benchmark shape, the Benchmark API surface, timer control,
sub-benchmarks, comptime-parametric generation, CLI flags, JSON
output, and the optimizer pitfall around trivial loops.
2026-05-21 08:22:50 +03:00
2610b8cf56 docs: bundled example benchmark suite
Examples covering the main usage patterns:

- bench_append_u8: per-iteration heap work, demonstrates B/op tracking
  via the wrapped allocator.
- bench_sha256_64: set_bytes() for throughput in MB/s.
- bench_integer_sum: shows the optimization pitfall with a comment —
  trivial loop bodies need an in-loop b.keep to survive ReleaseFast.
- bench_hash_sizes: parent that delegates to sub-benchmarks via b.run,
  printed as `hash_sizes/sha256_<size>`.
- memset_{16,256,4096}: comptime-parametric benchmark generation via
  std.fmt.comptimePrint + a generic gen_bench factory.

Includes a stand-alone examples/bench/build.zig illustrating the
zbench_build.add_bench_step integration a downstream project would use.
2026-05-21 08:13:28 +03:00
a763182b9d feat: public API and build helper for consumers
- root.zig: re-exports Benchmark, Suite, Options, Format, Result,
  BenchFn, parse_duration_ns; also pulls every submodule into the test
  block so `zig build test` covers them.
- build_helper.zig: add_bench_step(b, opts) factory that creates the
  benchmark executable (ReleaseFast by default), wires zbench and any
  extra modules, attaches an addRunArtifact forwarding `--` args, and
  registers a `zig build <step_name>` step.
2026-05-21 08:13:18 +03:00
4f5f693547 feat: reporters and CLI suite
- reporter.zig: text table writer (Go-compatible columns, mean ± stddev
  when --count > 1) and ndjson writer, both driving std.Io.Writer.
- suite.zig: Suite holds registered (name, fn) entries, owns name
  storage, drives run/run_cli, and routes sub-benchmark calls back
  through a sub_run trampoline using current_name to compose
  parent/child paths. Parses --filter / --min-time / --count /
  --max-iters / --allocs / --format / --list / --help, with a small
  duration parser (1s, 500ms, 100us, 250ns).
2026-05-21 08:13:08 +03:00
e28eb3c22e feat: core runner — counting allocator, stats, Benchmark, adaptive N
Adds the measurement core:

- CountingAllocator: a thin wrapper over std.mem.Allocator vtable that
  tracks alloc/free counts and total bytes allocated, exposing a reset()
  used between attempts of the adaptive loop.
- stats.summarize: min / mean / sample stddev over an array of f64,
  used to aggregate --count repetitions.
- Benchmark: user-facing handle passed to each bench fn — n,
  allocator (counting-wrapped), io, with snake_case methods
  reset_timer / stop_timer / start_timer / set_bytes / report_allocs /
  keep / run (sub-bench). Times via std.Io.Timestamp.now(io, .awake).
- runner.run_one: galloping iteration count toward --min-time, with
  ×100 growth cap per step and "nice-number" rounding, matching Go's
  testing pkg heuristic.
2026-05-21 08:12:56 +03:00
be72707042 chore: project scaffold and build wiring
Initial Zig 0.16 build script wiring the public `zbench` module, the
`zbench_build` helper module for downstream `build.zig` files, an
internal `test` step, and an `example` step that compiles and runs the
bundled benchmark suite.
2026-05-21 08:12:45 +03:00