Getting started

1. Install #

$ go install github.com/nao1215/himorime@latest

Other ways are on the Installation page.

2. Write a suite #

$ himorime init
wrote himorime.yaml
next: himorime validate himorime.yaml && himorime run himorime.yaml

himorime init writes a small suite that measures git --version. The first line points editors at the JSON Schema, so completion and validation work while you type. Replace the command with the program you care about:

# yaml-language-server: $schema=https://raw.githubusercontent.com/nao1215/himorime/main/schema/himorime.schema.json
version: "1"

name: my benchmarks

benchmarks:
  - name: help output
    commands:
      mytool:
        command: [mytool, --help]

A command is a list of arguments. It runs without a shell, so it behaves the same on Linux, macOS and Windows. Use a string with shell: true only when you need pipes or redirection.

3. Check it without running anything #

$ himorime validate
himorime.yaml: ok (1 benchmark, 1 command)

Mistakes are all reported at once, each with its file, line, column, field and, where there is one, a fix. Nothing runs, and the exit status is 2. A typo in command looks like this:

himorime.yaml:10:7: benchmarks[0].commands.mytool.command: command is required
himorime.yaml:11:9: benchmarks[0].commands.mytool.comand: unknown key "comand"
    hint: check the spelling against https://nao1215.github.io/himorime/configuration/; unknown keys are rejected so a typo cannot silently change a benchmark
himorime: the suite is invalid; nothing was run

4. Run it #

$ himorime run
suite: my benchmarks (himorime.yaml)
BENCHMARK    COMMAND  MEDIAN    MEAN    STDDEV  RELATIVE  RESULT
help output  mytool   2.10ms  2.14ms  110.30µs     1.00x  PASS
RELATIVE is the median divided by the baseline command's median, or by the fastest command's when no baseline is set.

1 passed · 1 benchmark · seed 5398001677524849 · exit 0

Without runs, himorime measures adaptively: at least 10 runs and 2 seconds per command, at most 100 runs. Progress goes to standard error and the report to standard output, so himorime run --format json > result.json stays clean.

5. Add budgets #

A budget is an upper or lower limit for a chosen statistic of one command. Latency is always measured; switch on the other metrics you care about:

version: "1"

name: my benchmarks

benchmarks:
  - name: help output
    metrics:
      cpu: true
      memory: true
    commands:
      mytool:
        command: [mytool, --help]
        budget:
          latency: {p95: "<= 50ms"}
          cpu_total: {median: "<= 30ms"}
          peak_rss: {max: "<= 32MiB"}
$ himorime run

The report now has a latency, a CPU, a memory and a budgets table. A missed budget says FAIL, and himorime exits 1. To declare throughput, tell himorime how much work one run does; see Metrics.

6. Compare with main #

To compare revisions, let the suite build the program and measure the build:

build:
  command: [go, build, -o, "${artifact}", ./cmd/mytool]

benchmarks:
  - name: help output
    commands:
      mytool:
        command: ["${artifact}", --help]
$ himorime compare --against main

himorime checks main out into a temporary Git worktree, builds both main and your working tree (uncommitted changes included), measures them interleaved on this machine, and exits 1 when a gated regression is statistically confirmed or a budget is exceeded. Your working tree, index and branches are not touched, and the worktree is removed even when you press Ctrl+C.

7. Run it on pull requests #

See GitHub Actions for a workflow that runs himorime ci on every pull request.