
# Teljesítménymérések

A teljesítménymérő keretrendszer stabil JSON adatokat és ember által olvasható jelentést ír. A(z)
`bench/` helyen található, a [storh tárolóban](https://github.com/inline0/storh), és a(z) 0.5.2 óta nem része a Composer csomagnak, ezért az alábbi `composer bench*` parancsok csak egy klónból futtathatók, a következő után: `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
```

## Referenciaeredmények

A keretrendszer három teljes futásának mediánjai, motoronként 50,000 rekorddal, egy
Apple M1 Pro gépen (16 GB, macOS 26.5, APFS), PHP 8.5 CLI mellett, kikapcsolt opcache és JIT esetén:

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

Minden írás kiüríti a puffert, és meghívja a fsync-et, mielőtt a(z) storh
tároltként jelentené. Ezért az írási sebességet a fájlrendszer korlátozza. Az olvasások
az operációs rendszer oldalgorsítótárából futnak. A sebességek mediánokból származnak;
saját hardverén a tároló klónjából futtassa a(z) `composer bench` parancsot.

| DocStore, 50k rekord | medián |
| ---------------------------------------------- | --------------- |
| `put()`, tartós rekordfájlonként | 3.3k rekord/s |
| `putStream()` tömeges betöltés | 3.7k rekord/s |
| `importJsonl()` | 3.6k rekord/s |
| `get()` pontszerű olvasás, STAT-ellenőrzéssel | 5.6 µs |
| meglévő tár újbóli megnyitása | 0.26 ms |
| indexelt egyenlőségi lekérdezés, `limit(100)` | 1.1 ms |
| indexelt `count()` a teljes gyűjteményen | 41 µs |
| indexépítés, 2 egyenlőségi + 1 tartománymező | 52k rekord/s |
| teljes `stream()` STAT-ellenőrzéssel | 103k rekord/s |
| `exportJsonl()` | 104k rekord/s |

| SegmentedLog, 50k rekord, 16 KB-os szegmensek | medián |
| ---------------------------------------------- | --------------- |
| `put()`, fsync minden hozzáfűzéskor | 16k hozzáfűzés/s |
| `appendStream()` tömeges betöltés | 56k rekord/s |
| kurzorolvasás, a 100 rekord a középponttól | 2.1 ms |
| időtartomány-olvasás | 1.1 ms |
| egyenlőségi `count()` | 11 µs |
| `compact()` az összes lezárt szegmensen | 69k rekord/s |
| újranyitás a csonka vég helyreállításával | 218k rekord/s |

A teljesítménymérő minden 16 KB után lezár egy szegmenst, hogy terhelje a
szegmensváltásokat; az alapértelmezett szegmensméret 1 MiB.

| Queue, 50k feladat | medián |
| ---------------------------------------------- | --------------- |
| `enqueue()`, fsync minden eseménynél | 22k feladat/s |
| `claim()` | 23k feladat/s |
| `complete()` | 23k feladat/s |
| `enqueueMany()` | 209k feladat/s |
| `claimMany()` | 467k feladat/s |
| `completeMany()` | 512k feladat/s |

| SQL Mirror, SQLite, 50k rekord | medián |
| ---------------------------------------------- | --------------- |
| kezdeti `push()` | 61k sor/s |
| `push()` változatlan adatokkal | 86k rekord/s |
| `flush()`, 100 azonosító | 7.1 ms |
| indexelt SQL `COUNT` a tükrön | 6.9 ms |
| `rebuild()` | 65k sor/s |
| `pull()` helyreállítás, tartós rekordfájlonként | 3.2k rekord/s |

| Micro | medián |
| ---------------------------------------------- | --------------- |
| gyorsítótárazott `get()`, hideg, majd meleg (MemoryCache, STAT) | 83 µs / 6.3 µs |
| UUIDv7 létrehozás | 1.3 µs |
| UUIDv7 ellenőrzés | 0.30 µs |
| memóriabeli predikátumszűrés | 4.4M sor/s |

Lefedett célok:

- DocStore put, streamelési put, JSONL export/import, get, delete, stream és indexépítés
- egyenlőségi indexelt, összetett indexelt, tartományindexelt, növekvő és csökkenő sorrendű tartomány, indexelt darabszám, ID-keresés és nem indexelt DocStore-lekérdezések
- SegmentedLog append, streamelési append, kurzorolvasás, időtartomány-olvasás, tömörített időtartomány-olvasás, QueryBuilder-kurzor és ID-keresés, darabszámok, tömeges hozzáfűzési darabszámok, statisztikák, tömörítés
- Queue enqueue, tömeges enqueue, claim, tömeges claim, complete, tömeges complete, requeue
- RecordQuery és QueryCondition predikátumszűrés memóriabeli sorokon
- UUIDv7 monoton generálás, időbélyeg-eloszlás szerinti generálás, érvényesítés és időbélyeg kinyerése
- helyreállítás a csonka záró sorokból
- hideg és meleg gyorsítótár-olvasások hash-, stat- vagy megbízható ellenőrzéssel

Alapértelmezett kimeneti útvonal:

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

A tartományfutások adathalmazonként és motoronként egy-egy JSON fájlt írnak a(z)
`build/bench-ranges/` alá.

A(z) `bench:gate` két teljesítménymérési JSON fájlt hasonlít össze, és nem nulla kilépési kóddal áll le, ha bármelyik követett mérőszám lassabb a beállított küszöbnél. Ha nem ad meg `--metric` értékeket, az alapfájlban szereplő összes mérőszámra vonatkozó korlátozást alkalmazza.

A(z) `bench:ci` a(z) GitHub Actions gyors regressziókapuja. 1k-s, minden motort érintő
mérést futtat, összehasonlítja a kiválasztott írási/olvasási/gyorsítótár/UUID
mérőszámokat a nyomon követett `bench/baselines/ci-1k-all.json` alapértékkel, és tág alapértelmezett küszöböt
használ, hogy kiszűrje a szokásos futtatókörnyezeti zajt, de jelezze a jelentős
teljesítmény-visszaeséseket.

A(z) `bench:jit` ugyanazt a keretrendszert futtatja bekapcsolt CLI opcache és nyomkövető JIT mellett, és letiltja a(z) Xdebug beállítást a mérési folyamat számára, hogy a(z) PHP ténylegesen bekapcsolhassa a JIT-et. A létrehozott JSON tartalmazza azokat a futásidejű jelzőket, amelyek megmutatják, hogy az opcache és a JIT aktív volt-e a futás során.
