Skip to content

Benchmark Baseline

Status — read this before quoting any number below.

The 2026-06-03 figures remain the authoritative baseline.

A full re-run was executed on 2026-08-01. It completed successfully — all six bench targets, 77 measurements, every one statistically tight — but it is rejected as a baseline because the host was running roughly 8x slower than normal for reasons unrelated to this project. Its numbers are recorded in the appendix for provenance and must not be compared against the 2026-06-03 table, nor cited as glaucus performance. See The 2026-08-01 re-run.


Fixtures

NameSourceSize
smallSMALL_POD — minimal Kubernetes Pod spec218 bytes
mediumMEDIUM_HELM — realistic Helm values.yaml3,364 bytes (~3.3 KB)
largegenerate_large(800) — 800-entry programmatic YAML124,579 bytes (~121.7 KB)

Sizes computed directly from crates/glaucus-bench/src/fixtures.rs. An earlier revision of this document recorded medium as "~5 KB", overstating it by about 50%; the source comments carried the same error and were corrected alongside this document.


Excluded competitor: serde_yml

serde_yml 0.0.13 is excluded from all benchmarks.

  • RUSTSEC-2025-0068 — unsound: a Serializer use-after-free can trigger a segfault in safe Rust.
  • The upstream repository is archived; no fix is expected.
  • Glaucus's deny.toml enforces vulnerability = "deny" with zero ignored advisories.

A commented-out entry in glaucus-bench/Cargo.toml documents this exclusion in-source.


Authoritative baseline — 2026-06-03

Branch: worktree-feat+beat-noyalibPurpose: establishes the measurement baseline for Phase 4b optimization work.

Environment

FieldValue
Toolchainrustc 1.93.1 (01f6ddf75 2026-02-11)
PlatformDarwin 24.6.0 x86_64 (Intel Mac, native x86_64)
CPUIntel Xeon W-2150B @ 3.00 GHz (Skylake-W, 10 cores)
System load at run time4.05 / 7.45 / 8.27 (1/5/15 min) — moderately loaded
Settings--warm-up-time 2 --measurement-time 8

Times are medians (middle value of Criterion's [low median high] bracket).

serde_deserialize

Deserializes each fixture into the library's generic value type. serde_json operates on the JSON-equivalent fixture and is a speed-of-light reference, not a YAML comparison.

Librarysmallmediumlarge
glaucus30.66 µs318.1 µs17.72 ms
noyalib49.43 µs232.3 µs10.79 ms
serde_yaml_ng33.43 µs343.4 µs18.82 ms
serde_saphyr57.85 µs571.7 µs33.51 ms
serde_json (JSON)3.94 µs49.51 µs3.09 ms

noyalib leads deserialize by ~1.4–1.6x at every size; glaucus holds 2nd, ahead of serde_yaml_ng by 6–8%. The gap is consistent across sizes, pointing to algorithmic overhead rather than a fixture-size effect.

serde_serialize

Librarysmallmediumlarge
glaucus8.50 µs81.93 µs3.70 ms
noyalib10.35 µs62.80 µs5.37 ms
serde_yaml_ng13.81 µs185.1 µs10.44 ms
serde_saphyr14.99 µs136.0 µs6.62 ms
serde_json (JSON)1.03 µs7.43 µs344 µs

Glaucus leads serialize at every size (1.2–1.45x over noyalib). The emitter's design — trusting the caller's ScalarStyle, no re-quoting overhead — pays off here.

roundtrip_compare (tree level)

Librarysmallmediumlarge
glaucus28.65 µs424.4 µs13.05 ms
yaml_rust233.49 µs414.1 µs15.08 ms
rust_yaml77.07 µs1.50 ms705.5 ms

Glaucus leads on small (~14%) and large (~13%); medium is a statistical tie with yaml_rust2. rust_yaml is ~54x slower on large inputs.


The 2026-08-01 re-run (rejected)

What was run

FieldValue
Date2026-08-01 06:56 UTC
Branch / commitmain @ daf377c
Toolchainrustc 1.97.1 (8bab26f4f 2026-07-14)
PlatformDarwin 24.6.0 x86_64, Intel Xeon W-2150B @ 3.00 GHz, 10 physical / 20 logical
Settings--warm-up-time 2 --measurement-time 8
ScopeAll six bench targets — 77 measurements
Wall time~85 min (scanner 289s, parser 371s, composer 1108s, emitter 605s, end_to_end 1639s, serde 1078s)
Load average during run34.2 – 39.4 throughout

target/criterion was cleared beforehand, so no change% figure in this run refers to a stale cached baseline — a caveat the previous revision had to carry.

Why it is rejected

Every one of the 30 measurements comparable to 2026-06-03 came out slower, by 4.57x to 20.89x (median 7.93x). The decisive evidence is serde_json — a third-party JSON library that glaucus does not touch, and which no change in this repository can affect:

Benchmark2026-06-032026-08-01Ratio
serde_deserialize/serde_json/small3.94 µs29.71 µs7.54x
serde_deserialize/serde_json/large3.09 ms14.11 ms4.57x
serde_serialize/serde_json/large344 µs7.19 ms20.89x
serde_deserialize/glaucus/small30.66 µs234.79 µs7.66x
serde_deserialize/noyalib/large10.79 ms115.35 ms10.69x

Confirmed independently of Criterion: a pure single-core integer loop with no I/O and no allocation took 5.19 s against roughly 0.4 s expected on a healthy 3.0 GHz W-2150B. The cores themselves were executing about an order of magnitude slow, which accounts for the whole effect.

Two consequences follow, and the second is the one that matters:

  1. Absolute times are inflated and cannot be compared with 2026-06-03.
  2. The degradation is not uniform (4.57x–20.89x), so it distorts the ratios between libraries as well. Even same-run rankings are unsafe to quote.

What is still trustworthy

The run is sound as a harness check, and that part is worth keeping:

  • All six bench targets built and completed with rc=0.
  • Criterion confidence intervals were tight throughout — spread between the low and high bounds had a median of 1.96% and a maximum of 4.2%. The measurements are precise; they are precisely measuring a slow machine.
  • Outlier rates of 3–12% per case are normal for Criterion.

Note that the load average was a poor signal here and nearly caused the wrong call in both directions: it read 34–39 while actual CPU utilisation was only ~13%, so it overstated contention — yet the machine really was degraded, for a reason load average never showed. The single-core calibration loop settled it; the load number alone would not have.

Before re-running

  1. Establish why the host is executing ~10x slow — thermal or power throttling on the W-2150B is the leading hypothesis and was not confirmed. Drift.appex, VTDecoderXPCService and WindowServer were all active during the window.
  2. Gate the run on the single-core calibration loop rather than on load average: require it near ~0.4 s before measuring.
  3. Note that the toolchain has also moved (1.93.1 → 1.97.1). That is a genuine confound for a future comparison, though far too small to explain 8x.

Appendix — full 2026-08-01 measurements

Do not cite these figures. They are recorded for provenance only, taken on a host running ~8x slow. Medians, with the width of Criterion's confidence interval as a percentage of the median.

scanner

Librarysmallmediumlargemax spread
glaucus70.59 µs706.95 µs35.09 ms±2.6%

parser

Librarysmallmediumlargemax spread
glaucus161.60 µs1.47 ms74.32 ms±2.9%
yaml_rust2178.95 µs1.87 ms92.45 ms±3.7%

composer

Librarysmallmediumlargemax spread
glaucus218.21 µs2.02 ms101.92 ms±1.8%
rust_yaml481.88 µs8.37 ms5429.20 ms±2.3%
yaml_rust2292.98 µs2.96 ms149.68 ms±2.5%

emitter

Librarysmallmediumlargemax spread
glaucus20.21 µs249.64 µs11.78 ms±2.3%
rust_yaml206.55 µs3.07 ms188.44 ms±2.2%
yaml_rust248.32 µs483.79 µs24.65 ms±2.1%

end_to_end

Group roundtrip_compare:

Librarysmallmediumlargemax spread
glaucus234.43 µs2.30 ms115.20 ms±2.1%
rust_yaml702.81 µs11.64 ms5673.80 ms±2.2%
yaml_rust2345.48 µs3.52 ms174.07 ms±2.3%

Group full_pipeline_node (two glaucus entry points, not competing libraries):

Pathsmallmediumlargemax spread
compose_all221.26 µs2.05 ms102.88 ms±2.6%
facade211.89 µs2.04 ms102.71 ms±2.6%

Group roundtrip_node:

Casemedianspread
small448.59 µs±1.9%
medium4.39 ms±1.6%
large216.68 ms±1.6%

Group typed_struct:

Casemedianspread
deserialize227.79 µs±2.3%
roundtrip270.59 µs±2.9%

serde

Group serde_deserialize:

Librarysmallmediumlargemax spread
glaucus234.79 µs2.27 ms114.13 ms±2.7%
noyalib247.05 µs2.33 ms115.35 ms±2.7%
serde_json29.71 µs314.42 µs14.11 ms±3.8%
serde_saphyr540.81 µs5.21 ms263.83 ms±2.5%
serde_yaml_ng306.70 µs3.18 ms151.26 ms±3.9%

Group serde_serialize:

Librarysmallmediumlargemax spread
glaucus43.25 µs525.33 µs30.14 ms±2.8%
noyalib65.23 µs679.35 µs32.85 ms±3.8%
serde_json12.78 µs154.82 µs7.19 ms±2.8%
serde_saphyr105.13 µs1.08 ms52.50 ms±4.2%
serde_yaml_ng147.92 µs1.52 ms72.15 ms±2.7%

Commands

bash
# One target at a time, never concurrently.
cargo bench -p glaucus-bench --bench <target> -- --measurement-time 8 --warm-up-time 2

# Targets: scanner parser composer emitter end_to_end serde

-p glaucus-bench rather than --workspace: --output-format and the other Criterion flags are rejected by the default libtest harnesses that --workspace also sweeps in, which aborts the run after the release build.


Standing caveats

  • serde_saphyr has no native value type. Both its deserialize and serialize rows use serde_json::Value as the data carrier, adding marginal JSON-side overhead but keeping the comparison consistent within the group.
  • ARM baseline still outstanding. A Linux aarch64 data point (raspi5) remains unmeasured; NEON path validation for the simd feature gate needs it.
  • serde_json rows are a speed-of-light reference, parsing JSON rather than YAML. They bound what the fixture data costs to materialise; they are not a YAML comparison.

Code released under MIT OR Apache-2.0. Documentation under CC-BY-3.0+.