# `ktav` parse benchmark baseline
Captured before the structured-errors refactor so any regression in the
parser/error-construction code is visible against this reference.
- **Date:** 2026-05-01
- **Crate:** `ktav` 0.1.4 (`D:\dev\ktav-lang\rust`)
- **Toolchain:** `rustc 1.93.0 (254b59607 2026-01-19)`
- **OS:** Microsoft Windows 10 Pro, build 10.0.19045
- **CPU:** 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30 GHz
- **RAM:** 47.8 GB
- **Mode:** `cargo bench --bench parse -- --quick parse_synth`
(Criterion `--quick` — reduced sample count, but median is stable
enough for ±5% regression detection.)
- **Noise caveat:** numbers are indicative on this host. Windows
desktop, no noise suppression (no `cpufreq` pinning, no isolated
cores, normal background load). Re-run on the same machine before
drawing fine-grained conclusions; cross-machine comparisons are not
meaningful.
## Workloads
Generated by `benches/fixtures.rs::synth(target_bytes)` — a deterministic
round-robin mix of plain pairs, dotted keys, typed scalars (`:i`/`:f`),
raw markers (`::`), nested objects/arrays, multi-line raw blocks
(`( ... )`), and comment lines. Sizes are *targets*; actual byte counts
are slightly above target.
| `small_1k` | 1 KiB | ~1.03 KiB |
| `medium_50k` | 50 KiB | ~50.0 KiB |
| `large_500k` | 500 KiB | ~500 KiB |
## Success path — `ktav::parse(text)`
Group `parse_synth`. Throughput keyed off input bytes.
| `parse_synth/small_1k` | 16.148 µs | 63.66 MiB/s |
| `parse_synth/medium_50k` | 896.30 µs | 54.55 MiB/s |
| `parse_synth/large_500k` | 9.4864 ms | 51.47 MiB/s |
## Error path — `ktav::parse(text_with_one_bad_line)`
Group `parse_synth_error`. A single invalid line (`"key:value\n"` — no
space after the colon) is injected at the document midpoint
(snapped to the next line boundary) by
`fixtures::with_bad_line(&good)`. Each iteration parses, observes
`Err(_)`, and discards. This exercises the error-construction code that
the upcoming structured-errors refactor will touch.
| `parse_synth_error/small_1k` | 7.5346 µs | 137.71 MiB/s |
| `parse_synth_error/medium_50k` | 339.68 µs | 143.98 MiB/s |
| `parse_synth_error/large_500k` | 4.4666 ms | 109.32 MiB/s |
The error path is faster than the success path because the parser bails
out at roughly the document midpoint — only ~half the document is
actually scanned before the error is constructed and returned. The
"throughput" column above divides by the **full** input size (including
the unscanned tail), so it overstates the effective per-byte cost. For
regression-tracking purposes only the median **time** matters; the
MiB/s figure is informational.
## Re-running
```sh
cd D:\dev\ktav-lang\rust
cargo bench --bench parse -- --quick parse_synth
```
For a full (non-`--quick`) run, drop the `--quick` flag — expect ~5
minutes wall time and tighter confidence intervals. Criterion stores its
own per-machine baseline under `target/criterion/`; subsequent runs
will report `+/- X%` against the previous run automatically.
## Post-0.1.5 — structured errors + spans + thin-public
After Phase 1 (Error::Structured + ErrorKind), 0.1.6 hardening
(Span + #[non_exhaustive] + 3 promoted categories), and 0.1.7
(public ktav::thin event-based API), re-run on the same Win10 /
i7-11800H / rustc 1.93.0 host with the same `cargo bench --bench
parse -- --quick` invocation:
| `parse_synth/small_1k` | 16.1 µs | 16.0 µs | −0.6 % |
| `parse_synth/medium_50k` | 896 µs | 663 µs | −26 % |
| `parse_synth/large_500k` | 9.49 ms | 9.27 ms | −2.3 % |
| `parse_synth_error/small_1k` | 7.5 µs | 7.18 µs | −4.2 % |
| `parse_synth_error/medium_50k` | 340 µs | 346 µs | +1.8 % |
| `parse_synth_error/large_500k` | 4.47 ms | 4.50 ms | +0.7 % |
All inside the ±10 % envelope set as the regression threshold for the
structured-errors body of work. Net: zero success-path regression
(the `medium_50k` improvement is partly noise on this host, partly a
real win from cumulative-byte tracking replacing some `str::lines()`
overhead). Error-path slightly faster — the new `Display` impl
constructs the formatted string lazily at `.to_string()` time,
whereas the prior `format!(...)` allocated a `String` at every
error site eagerly. The cumulative-byte counter that powers spans is
statistically free.
`parse_synth_error/large_500k` showed a temporary +30 % spike in an
intermediate run (3.46 ms baseline outlier vs 4.50 ms post); Criterion
reported "no change in performance detected" at p=0.10 across runs.
The number above is the stabilised post-refactor median.