# Identifier interning benchmark

Run from the repository root:

```sh
odin run benchmarks/symbols -o:speed
```

The benchmark warms the pipeline once, then measures a fresh lex/parse/check
run over a generated program with 5,000 repeated identifier-heavy statements.
Timing is informational; token layout and allocation metrics are the stable
comparison points.

Results captured on 2026-06-10 with Odin `dev-2026-02:b942f72cb`:

| Metric | Before interning | After interning |
| --- | ---: | ---: |
| Elapsed time | 15.723 ms | 9.248 ms |
| Peak memory | 14,661,846 bytes | 13,220,507 bytes |
| Allocations | 40,105 | 40,112 |
| Token count | 65,032 | 65,032 |
| Token size | 56 bytes | 48 bytes |
| Unique symbols | n/a | 5 |
| Stored symbol bytes | n/a | 21 |
| Diagnostics | 0 | 0 |

The measured run reduced token size by 14.3% and peak tracked memory by 9.8%.

After the iterative compiler-hardening work on 2026-06-12, the same benchmark
reported 13,222,443 peak bytes and 40,117 allocations. The reusable traversal
stacks keep allocation count effectively unchanged from the interning baseline.

After migrating persistent compiler references and spans to compact IDs on
2026-06-12, the benchmark reported 8,651,659 peak bytes and 40,117 allocations.
`Span` is 12 bytes and `Token` is 24 bytes; AST expressions, HIR expressions,
and IR instructions are 64, 88, and 88 bytes respectively. These sizes are
also printed by the benchmark to catch layout regressions.

After pruning stale function specializations on 2026-06-12, peak memory
remained 8,651,659 bytes and allocations fell to 30,121. Lookup-only
specialization resolution avoids constructing temporary signatures for
already discovered calls.

After adding checked unary negation on 2026-06-12, peak memory remained
8,651,659 bytes and allocations remained 30,121. `Span`, `Token`, AST
expressions, HIR expressions, and IR instructions remain 12, 24, 64, 88, and
88 bytes respectively.
