
# Võrdlustestid

Võrdlustestide raamistik kirjutab stabiilse JSON ja inimloetava aruande. See asub
asukohas `bench/` [storh hoidlas](https://github.com/inline0/storh) ja pole olnud Composer paketi osa alates versioonist 0.5.2, seega käivitage alltoodud `composer bench*` käsud ainult hoidla kloonist, pärast `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
```

## Võrdlustulemused

Kolme täieliku raamistiku käivituse mediaanid, 50,000 kirjet mootori kohta, seadmel
Apple M1 Pro (16 GB, macOS 26.5, APFS), kus PHP 8.5 CLI, opcache ja JIT olid välja lülitatud:

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

Iga kirjutis tühjendatakse ja fsync kutsutakse välja enne, kui storh teatab selle salvestatuks, mistõttu kirjutuskiirust piirab failisüsteem. Lugemisel kasutatakse operatsioonisüsteemi lehevahemälu. Kiirused arvutatakse mediaanide põhjal; oma riistvara tulemuste saamiseks käivitage hoidla kloonis `composer bench`.

| DocStore, 50k kirjet                         | mediaan         |
| ---------------------------------------------- | --------------- |
| `put()`, üks püsiv fail kirje kohta           | 3.3k kirjet/s   |
| `putStream()` hulgi lisamine                   | 3.7k kirjet/s   |
| `importJsonl()`                                | 3.6k kirjet/s   |
| `get()` üksikkirje lugemine, STAT-kontrolliga | 5.6 µs          |
| olemasoleva hoidla taasavamine               | 0.26 ms         |
| indekseeritud võrduspäring, `limit(100)`           | 1.1 ms          |
| indekseeritud `count()` kogu kogu ulatuses      | 41 µs           |
| indeksi koostamine, 2 võrdsus- ja 1 vahemikuväli | 52k kirjet/s |
| täielik `stream()` koos STAT-i korduskontrolliga | 103k kirjet/s  |
| `exportJsonl()`                                | 104k kirjet/s   |

| SegmentedLog, 50k kirjet, 16 KB segmendid       | mediaan         |
| ---------------------------------------------- | --------------- |
| `put()`, fsync iga lisamise järel               | 16k lisamist/s  |
| `appendStream()` hulgi lisamine                    | 56k kirjet/s   |
| kursori lugemine, 100 kirjet keskelt          | 2.1 ms          |
| ajavahemiku lugemine                            | 1.1 ms          |
| võrdsuspäring `count()`                             | 11 µs           |
| `compact()` kõik suletud segmendid                 | 69k kirjet/s   |
| taasavamine koos pooliku lõpu taastamisega       | 218k kirjet/s  |

Võrdlustestis suletakse segment iga 16 KB järel, et koormata segmentide vahetamist; vaikimisi segmendi suurus on 1 MiB.

| Queue, 50k tööd                              | mediaan         |
| ---------------------------------------------- | --------------- |
| `enqueue()`, fsync iga sündmuse järel              | 22k tööd/s      |
| `claim()`                                      | 23k tööd/s      |
| `complete()`                                      | 23k tööd/s      |
| `enqueueMany()`                                      | 209k tööd/s     |
| `claimMany()`                                      | 467k tööd/s     |
| `completeMany()`                                      | 512k tööd/s     |

| SQL Mirror, SQLite, 50k kirjet                 | mediaan         |
| ---------------------------------------------- | --------------- |
| esialgne `push()`                               | 61k rida/s      |
| `push()`, kui midagi pole muutunud               | 86k kirjet/s   |
| `flush()`, 100 ID-d                              | 7.1 ms          |
| indekseeritud SQL `COUNT` üle peegli             | 6.9 ms          |
| `rebuild()`                                    | 65k rida/s      |
| `pull()` taastamine, üks püsiv fail kirje kohta | 3.2k kirjet/s  |

| Micro                                      | mediaan                         |
| ---------------------------------------------- | --------------- |
| vahemällu salvestatud `get()`, külm ja seejärel soe (MemoryCache, STAT) | 83 µs / 6.3 µs |
| UUIDv7 genereerimine                              | 1.3 µs          |
| UUIDv7 kontrollimine                              | 0.30 µs         |
| mälus predikaadiga filtreerimine                  | 4.4M rida/s     |

Kaetud sihtmärgid:

- DocStore'i lisamine, voogedastusega lisamine, JSONL eksport/import, hankimine, kustutamine, voogedastus ja indeksi koostamine
- võrdusindeksiga, liitindeksiga, vahemikuindeksiga päringud, kasvavas ja kahanevas järjestuses vahemikupäringud, indekseeritud loendus, ID otsing ja indekseerimata DocStore'i päringud
- SegmentedLogi lisamine, voogedastusega lisamine, kursori lugemised, ajavahemiku lugemised, tihendatud ajavahemiku lugemised, QueryBuilderi kursori- ja ID-otsingud, loendused, hulgi lisamise loendused, statistika, tihendamine
- Queue'i lisamine, hulgi lisamine, hõivamine, hulgi hõivamine, lõpetamine, hulgilõpetamine, uuesti järjekorda lisamine
- RecordQuery ja QueryConditioni predikaatfiltreerimine mälus olevate ridade põhjal
- UUIDv7 monotoonne genereerimine, ajatempli hajutusega genereerimine, valideerimine ja ajatemplite eraldamine
- pooliku lõpurea taastamine
- külma ja sooja vahemälu lugemised räsi-, oleku- või usaldatud valideerimisega

Väljundi vaikimisi asukoht:

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

Vahemiktestid kirjutavad iga andmestiku ja mootori kohta ühe JSON faili asukohta
`build/bench-ranges/`.

`bench:gate` võrdleb kahte võrdlustesti JSON faili ja tagastab nullist erineva väljumiskoodi, kui mõni jälgitav mõõdik on seadistatud lävest aeglasem. Kui `--metric` väärtusi pole antud, rakendab see piirangut kõigile baastaseme failis olevatele mõõdikutele.

`bench:ci` on GitHub Actions jõudluse taandarengu kiirkontroll. See käivitab kõigi mootorite 1k võrdlustesti, võrdleb valitud kirjutamise, lugemise, vahemälu ja UUID mõõdikuid jälgitava `bench/baselines/ci-1k-all.json` baastasemega ning kasutab vaikimisi laia läve, et tavaline käituskeskkonna müra tulemust ei mõjutaks, kuid suured jõudluse langused põhjustaksid siiski vea.

`bench:jit` käivitab sama raamistiku, kasutades CLI opcache'i ja jälgivat JIT-i,
ning keelab võrdlustesti protsessis Xdebug, et PHP saaks JIT-i tegelikult sisse lülitada.
Loodud JSON sisaldab käituslippe, mis näitavad, kas opcache ja JIT olid selle käivituse ajal aktiivsed.
