
# Benchmarkresultater

Benchmark-harnessen skriver stabile JSON og en rapport, der er let at læse. Den ligger i `bench/` i [storh-repositoryet](https://github.com/inline0/storh) og har ikke været en del af pakken Composer siden 0.5.2, så `composer bench*`-kommandoerne nedenfor kan kun køres fra en klon, efter `composer install`:

```bash
composer bench
composer bench -- --dataset=100000 --engine=doc
composer bench -- --dataset=100000 --engine=log
composer bench -- --dataset=100000 --engine=queue
composer bench -- --dataset=100000 --engine=cache --cache-validation=trust
composer bench -- --dataset=100000 --engine=filter
composer bench -- --dataset=1000000 --engine=uuid
composer bench:jit -- --dataset=1000000 --engine=uuid
composer bench:repeat -- --dataset=100000 --engine=doc --repeat=5
composer bench:repeat -- --dataset=1000000 --engine=filter --repeat=5 --memory-limit=512M
composer bench:range -- --datasets=1000,10000,50000,100000
composer bench:range -- --datasets=100000 --engines=cache --memory-limit=512M
composer bench:compare build/bench-main.json build/bench-current.json
composer bench:gate -- build/bench-main.json build/bench-current.json --threshold=10 --metric=doc.put --metric=log.stream
composer bench:ci
```

## Referenceresultater

Medianer fra tre fulde kørsler af værktøjet med 50,000 poster pr. motor på en Apple M1 Pro (16 GB, macOS 26.5, APFS) med PHP 8.5 CLI, opcache og JIT slået fra:

```bash
composer bench:repeat -- --dataset=50000 --engine=all --repeat=3 --memory-limit=512M
```

Hver skrivning tømmes og fsync-køres, før storh melder, at den er gemt, så skrivehastigheden begrænses af filsystemet. Læsninger bruger operativsystemets sidecache. Hastighederne er beregnet ud fra medianerne. Kør `composer bench` fra en klon af repositoryet for at måle din egen hardware.

| DocStore, 50k poster                          | median          |
| ---------------------------------------------- | --------------- |
| `put()`, én varig fil pr. post                  | 3.3k poster/s   |
| `putStream()` masseindlæsning                         | 3.7k poster/s   |
| `importJsonl()`                                         | 3.6k poster/s   |
| `get()` punktlæsning, STAT-valideret             | 5.6 µs          |
| genåbning af et eksisterende lager              | 0.26 ms         |
| indekseret lighedssøgning, `limit(100)`               | 1.1 ms          |
| indekseret `count()` på tværs af samlingen         | 41 µs           |
| indeksbygning, 2 lighedsfelter + 1 intervalfelt | 52k poster/s    |
| fuld `stream()` med STAT-genvalidering               | 103k poster/s   |
| `exportJsonl()`                                         | 104k poster/s   |

| SegmentedLog, 50k poster, 16 KB-segmenter         | median          |
| ------------------------------------------------- | --------------- |
| `put()`, fsync ved hver tilføjelse                 | 16k tilføjelser/s |
| `appendStream()` masseindlæsning                            | 56k poster/s     |
| markørlæsning, 100 poster fra midten           | 2.1 ms           |
| intervalaflæsning efter tid                        | 1.1 ms           |
| lighedssøgning `count()`                              | 11 µs            |
| `compact()` alle forseglede segmenter                   | 69k poster/s     |
| genåbning med gendannelse af afbrudt afslutning    | 218k poster/s    |

Benchmarken forsegler et segment for hver 16 KB for at stresse segmentskift; standardsegmentstørrelsen er 1 MiB.

| Kø, 50k job                                 | median          |
| ------------------------------------------- | --------------- |
| `enqueue()`, fsync for hver hændelse             | 22k job/s       |
| `claim()`                                       | 23k job/s       |
| `complete()`                                       | 23k job/s       |
| `enqueueMany()`                                       | 209k job/s      |
| `claimMany()`                                       | 467k job/s      |
| `completeMany()`                                       | 512k job/s      |

| SQL Mirror, SQLite, 50k poster              | median          |
| --------------------------------------------- | --------------- |
| indledende `push()`                             | 61k rækker/s    |
| `push()` uden ændringer                         | 86k poster/s   |
| `flush()`, 100 id'er                          | 7.1 ms         |
| indekseret SQL `COUNT` i hele spejlet       | 6.9 ms         |
| `rebuild()`                                         | 65k rækker/s   |
| `pull()`-gendannelse, én varig fil pr. post     | 3.2k poster/s |

| Mikro                                         | median          |
| ---------------------------------------------- | --------------- |
| cachelagret `get()`, kold derefter varm (MemoryCache, STAT) | 83 µs / 6.3 µs |
| UUIDv7 generér                                | 1.3 µs          |
| UUIDv7 validér                                | 0.30 µs         |
| filtrering med in-memory-predicate            | 4.4M rækker/s   |

Dækkede mål:

- DocStore put, streaming put, JSONL eksport/import, get, delete, stream og indeksopbygning
- lighedsindekserede, sammensat-indekserede, områdeindekserede, stigende og faldende ordnede områdeforespørgsler, indekseret optælling, ID-opslag og ikke-indekserede DocStore-forespørgsler
- SegmentedLog append, streaming append, markørlæsninger, tidsområdelæsninger, komprimerede tidsområdelæsninger, QueryBuilder-markør- og ID-opslag, optællinger, masseappend-optællinger, statistik, komprimering
- Queue enqueue, masse-enqueue, claim, masse-claim, complete, masse-complete, requeue
- filtrering med RecordQuery- og QueryCondition-predicate over rækker i hukommelsen
- UUIDv7 monoton generering, generering med tidsstempelfordeling, validering og udtræk af tidsstempel
- gendannelse efter afbrudt afsluttende linje
- kolde og varme cachelæsninger med hash-, stat- eller betroet validering

Standardsti for output:

```text
build/bench-current.json
```

Områdekørsler skriver én JSON-fil pr. datasæt og motor under
`build/bench-ranges/`.

`bench:gate` sammenligner to benchmarkfiler JSON og afslutter med en statuskode, der ikke er nul, hvis en målt metrik er langsommere end den konfigurerede tærskel. Hvis der ikke angives nogen `--metric`-værdier, kontrolleres alle metrikker i baselinefilen.

`bench:ci` er GitHub Actions-røggaten for regressioner. Den kører en benchmark med 1k for alle motorer, sammenligner udvalgte målinger for skrivning/læsning/cache/UUID med den registrerede `bench/baselines/ci-1k-all.json`-baseline og bruger en bred standardtærskel for at undgå normal støj fra kørsler, samtidig med at den stadig fanger store ydelsesregressioner.

`bench:jit` kører samme testopsætning med CLI opcache og sporings-JIT aktiveret og deaktiverer Xdebug for benchmarkprocessen, så PHP faktisk kan aktivere JIT.
Den genererede JSON indeholder kørselsflag, der viser, om opcache og JIT var aktive under kørslen.
