Performance Benchmarks¶
Hornet is built on winnow, a zero-copy, monomorphising parser combinator library designed for throughput. Benchmarks are measured with Criterion.rs (100 statistical samples per group).
Test environment¶
| Property | Value |
|---|---|
| Platform | macOS 15 (Apple M-series) |
| Rust | stable (1.86+) |
| Profile | release (opt-level = 3) |
| Criterion warm-up | 3 s |
| Criterion measurement | 5 s |
Note
Linux x86_64 builds show comparable throughput. CI benchmarks run on ubuntu-latest
and results are uploaded as workflow artifacts for reference.
named.conf — parsing¶
Seven fixture sizes from a trivial single-block config up to a 50 000-zone stress test.
The first five (tiny → xlarge) are run in standard CI; the last two are run via
make bench-stress only.
| Fixture | Input size | Median time | Throughput | CI? |
|---|---|---|---|---|
tiny — single options block |
60 B | 596 ns | 102 MiB/s | ✓ |
small — options + ACL + 3 zones + logging |
~700 B | 7.9 µs | 87 MiB/s | ✓ |
medium — views, ACLs, keys, logging, 11 zones |
~2.8 KB | 34 µs | 81 MiB/s | ✓ |
large — 100 zones |
~12 KB | 218 µs | 54 MiB/s | ✓ |
xlarge — 1 000 zones |
~124 KB | 13.8 ms | 8.7 MiB/s | ✓ |
xxlarge — 10 000 zones (stress) |
~1.3 MB | 1.19 s | 1.02 MiB/s | — |
xxxlarge — 50 000 zones (stress) |
~6.5 MB | 30.5 s | 207 KiB/s | — |
Typical production configs
Real-world named.conf files rarely exceed 50 KB. At the medium fixture scale (a realistic
multi-view production config), hornet parses in under 35 µs.
Scaling behaviour beyond 1 000 zones
Throughput drops significantly past ~1 000 zones due to heap allocation pressure and CPU
cache spill as the in-memory AST grows. For configs in that range, consider splitting across
multiple include files or using the view mechanism to partition zones.
named.conf — writing and validation¶
Using the medium fixture (~2.8 KB, 11 zones across 2 views).
| Operation | Median time | Throughput |
|---|---|---|
write_named_conf |
12.9 µs | 212 MiB/s |
validate_named_conf |
967 ns | 2.77 GiB/s |
| Round-trip (parse + write) | 46.6 µs | 59 MiB/s |
Zone files — parsing¶
Five fixture sizes from a minimal zone (SOA + NS + 2 A records) up to 10 000 host records.
| Fixture | Input size | Median time | Throughput |
|---|---|---|---|
tiny — SOA + NS + 2 A records |
~200 B | 2.1 µs | 85 MiB/s |
small — 20 records, all major types |
~1 KB | 8.4 µs | 134 MiB/s |
medium — 100 A records |
~5.5 KB | 24.7 µs | 91 MiB/s |
large — 1 000 A records |
~55 KB | 228 µs | 99 MiB/s |
xlarge — 10 000 A records |
~550 KB | 2.3 ms | 104 MiB/s |
Consistent linear scaling
Zone file throughput stays in the 85–106 MiB/s band across four orders of magnitude of input size, demonstrating the linear complexity of the winnow parser combinators.
Zone files — writing and validation¶
Using the medium fixture (100 records, ~5.5 KB).
| Operation | Median time | Throughput |
|---|---|---|
write_zone_file |
18.5 µs | 121 MiB/s |
validate_zone_file |
110 ns | 19.7 GiB/s |
| Round-trip (parse + write) | 45.4 µs | 49 MiB/s |
Running the benchmarks yourself¶
# Full run (uses Criterion defaults: 3 s warm-up, 5 s measurement)
make bench
# Abbreviated run, standard fixtures only (used in CI)
make bench-quick
# Stress fixtures only — 10k and 50k zones (slow)
make bench-stress
# Compile only — verify bench code builds without running
make bench-compile
Criterion generates an interactive HTML report at target/criterion/report/index.html.
Comparing against a baseline¶
# Save a baseline labelled "main"
cargo bench -- --save-baseline main
# Later, compare a branch against it
cargo bench -- --load-baseline main --baseline main
Source¶
Benchmark source lives in benches/:
benches/named_conf.rs— parse, write, validate, round-trip (tiny → xlarge 1k zones)benches/named_conf_stress.rs— stress fixtures (10k and 50k zones, not run in CI)benches/zone_file.rs— parse, write, validate, round-trip for zone files