adotenv 0.10.4

A tooling-grade .env parser: literal values (no variable expansion), exact byte spans, and edits that leave the rest of the file untouched.
Documentation
# Performance

These are local reference measurements, not CI thresholds.

## Method

- Reference host: kbench, Intel Core i7-6700HQ, 4 cores and 8 threads, 2.6 GHz,
  Linux x86_64, rustc 1.97.0. The benchmark process was pinned to one CPU.
- Release build with a fixed fixture generator.
- `cargo bench -p adotenv --bench core --locked -- --sample-size 20 --measurement-time 2`
- The host was otherwise idle. Wall time is recorded; instruction counts are the
  stable CPU comparison for cross-library work.

## Core workloads

| Workload | 8 entries | 128 entries | 65,536 entries |
|---|---:|---:|---:|
| parse | 6.29 us | 99.8 us | 62.4 ms |
| lookup index build | 136.6 ns | 2.36 us | 3.40 ms |
| indexed get, 64 keys | 195.8 ns | 1.63 us | 1.76 us |
| portability, 4 presets | 62.8 us | 1.09 ms | 745 ms |
| references | 507.6 ns | 7.94 us | 4.64 ms |
| resolve | 7.23 us | 173.9 us | 118.9 ms |
| sort | 3.19 us | 278.6 us | 161.1 ms |
| format normalize | 8.30 us | 135.8 us | 76.7 ms |
| native set | 10.4 us | 102.4 us | 61.7 ms |
| native batch | 8.33 us | 102.9 us | 63.6 ms |

`Document::get` scans entries. For many lookups, build `Document::lookup_index`
once. The index uses a compact open-addressed table with an ordered fallback for
collision-heavy input.

## Parser memory

One 65,536-entry document with a 1.8 MB source:

- live after parse: 23.6 MB;
- peak parse: 32.0 MB;
- parse plus collected map: 4.6 MB live after the document is dropped.

Retained document memory is dominated by item and token metadata. Values-only
loading avoids the document entirely.

## Loading memory

One 65,536-entry file on a release build:

| Profile | Peak | Retained |
|---|---:|---:|
| Default | 47.7 MB | 28.0 MB |
| `LoadOptions::full` | 57.4 MB | 37.7 MB |
| Values only | 11.2 MB | 10.0 MB |

The default keeps values, shared-file origins and raw tokens. Reports add entry,
override, repeat and skipped vectors. Values-only loading projects values while
parsing and retains no document or provenance.

The default profile now stores value, origin and raw-token data in one record
per key. This removes two per-key maps from the retained loader.

## Budgets

The comparison harness is the source of these budgets. Reference results are
recorded on the kbench host. Run the full check with:

```console
python3 scripts/compare.py --check-budgets
```

| Profile | Instructions | Peak RSS | Retained RSS |
|---|---:|---:|---:|
| adotenv parse | 260M | not budgeted | 29 MB |
| adotenv parse + values | 400M | 12 MB | 12 MB |
| adotenv parse + map | 335M | not budgeted | 16 MB |
| values-only load | 400M | 13 MB | 11.5 MB |
| default load | 560M | 50 MB | 30 MB |
| full-report load | 750M | 60 MB | 40 MB |

The parse-only binary budget is 500 KB. Wall time is recorded but not enforced
because the shared host is too noisy for a hard threshold.

A release blocks above the instruction or memory budget until the regression is
fixed or explicitly accepted. A wall-time result between 1.5x and 2x requires a
repeat run and an explanation; above 2x blocks the release.

## Diff and matrix

For three 65,536-entry files:

- streaming two-file diff with indexed comparison: about 73.3 MB peak and 0.6 s;
- matrix diff with compact incremental rows: about 103.0 MB peak and 0.8 s.

Matrix output retains one row per key because every column is needed. Two-file
diff streams candidates and buffers output until all candidates validate.

## Comparison with other parsers

The closest comparison is `adotenv::parse` followed by collecting effective
values. Other crates return maps or load into the environment directly.

Fixture: 65,536 compatible declarations, 1.8 MB source.

| Implementation | Instructions | Live memory | Peak |
|---|---:|---:|---:|
| adotenv parse | 272M | 23.6 MB | 32.0 MB |
| adotenv parse + map | 377M | 4.6 MB | 32.0 MB |
| dotenvy iterator + Vec | 373M | 5.0 MB | 15.7 MB |
| dotenv-compat parse | 307M | 9.5 MB | 18.6 MB |
| dotenv-ng input-only load | 406M | 7.9 MB | 20.4 MB |
| dotenv-parser map | 1,488M | 7.1 MB | 50.1 MB |

adotenv retains more syntax than the other parsers, including spans, items and
diagnostics. Values-only loading removes that overhead when it is not needed.

## Budget

- CI runs benchmark smoke only.
- Compare repeated runs on the same host and toolchain.
- A 1.5x deviation needs a repeat run and an explanation.
- A 2x deviation blocks a release until it is explained or fixed.
- Update this file when fixtures, compiler major version or methodology change.