Výkonnostné testy
Testovací rámec na porovnávanie výkonu zapisuje stabilné výsledky JSON a čitateľnú správu. Nachádza sa v bench/ v repozitári storh a od verzie 0.5.2 už nie je súčasťou balíka Composer, takže nasledujúce príkazy composer bench* možno spustiť iba z klonu po vykonaní composer install:
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
Referenčné výsledky
Mediány z troch úplných behov testovacieho rámca, 50,000 záznamov na každý modul, na zariadení Apple M1 Pro (16 GB, macOS 26.5, APFS) s PHP 8.5 CLI, vypnutými opcache a JIT:
composer bench:repeat -- --dataset=50000 --engine=all --repeat=3 --memory-limit=512M
Každý zápis sa pred nahlásením uloženia storh vyprázdni a fsyncuje, preto rýchlosť zápisu obmedzuje súborový systém. Čítanie využíva vyrovnávaciu pamäť stránok operačného systému. Rýchlosti sú odvodené z mediánov; vlastný hardvér otestujte spustením composer bench z klonu repozitára.
| DocStore, 50k záznamov | medián |
|---|---|
put(), jeden trvalý súbor na záznam |
3.3k záznamov/s |
putStream() hromadné načítanie |
3.7k záznamov/s |
importJsonl() |
3.6k záznamov/s |
get() čítanie podľa ID, overené pomocou STAT |
5.6 µs |
| opätovné otvorenie existujúceho úložiska | 0.26 ms |
indexovaný dopyt na rovnosť, limit(100) |
1.1 ms |
indexované count() naprieč kolekciou |
41 µs |
| zostavenie indexu, 2 polia rovnosti + 1 rozsahové pole | 52k záznamov/s |
úplné stream() s opätovným overením pomocou STAT |
103k záznamov/s |
exportJsonl() |
104k záznamov/s |
| SegmentedLog, 50k záznamov, segmenty s veľkosťou 16 KB | medián |
|---|---|
put(), fsync pri každom pridaní |
16k pridaní/s |
appendStream() hromadné načítanie |
56k záznamov/s |
| čítanie kurzorom, 100 záznamov od stredu | 2.1 ms |
| čítanie podľa časového rozsahu | 1.1 ms |
count() na rovnosť |
11 µs |
compact() všetkých uzavretých segmentov |
69k záznamov/s |
| opätovné otvorenie s obnovou odrezaného konca | 218k záznamov/s |
Test výkonu uzatvára segment každých 16 KB, aby zaťažil prechody medzi segmentmi; predvolená veľkosť segmentu je 1 MiB.
| Queue, 50k úloh | medián |
|---|---|
enqueue(), fsync pri každej udalosti |
22k úloh/s |
claim() |
23k úloh/s |
complete() |
23k úloh/s |
enqueueMany() |
209k úloh/s |
claimMany() |
467k úloh/s |
completeMany() |
512k úloh/s |
| SQL Mirror, SQLite, 50k záznamov | medián |
|---|---|
počiatočné push() |
61k riadkov/s |
push() bez zmien |
86k záznamov/s |
flush(), ID 100 |
7.1 ms |
indexované SQL COUNT nad zrkadlom |
6.9 ms |
rebuild() |
65k riadkov/s |
obnovenie pull(), jeden trvalý súbor na záznam |
3.2k záznamov/s |
| Micro | medián |
|---|---|
uložené v cache get(), najprv studené, potom teplé (MemoryCache, STAT) |
83 µs / 6.3 µs |
| generovanie UUIDv7 | 1.3 µs |
| overovanie UUIDv7 | 0.30 µs |
| filtrovanie predikátom v pamäti | 4.4M riadkov/s |
Pokryté ciele:
- DocStore put, streaming put, export/import JSONL, get, delete, stream a zostavenie indexu
- dopyty DocStore indexované podľa rovnosti, zloženého indexu a rozsahu, usporiadané rozsahy vzostupne a zostupne, počet cez index, vyhľadávanie podľa ID a dopyty bez indexu
- SegmentedLog append, streaming append, čítanie kurzorom, čítanie podľa časového rozsahu, čítanie podľa kompaktného časového rozsahu, vyhľadávanie kurzorom a podľa ID cez QueryBuilder, počty, počty hromadného pridávania, štatistiky, kompakcia
- Queue enqueue, hromadné enqueue, claim, hromadné claim, complete, hromadné complete, requeue
- filtrovanie predikátom RecordQuery a QueryCondition nad riadkami v pamäti
- generovanie monotónnych hodnôt UUIDv7, generovanie s rozptýlenými časovými značkami, overovanie a extrakcia časovej značky
- obnova po odrezanom koncovom riadku
- čítanie studenej a teplej cache s overením pomocou hash, stat alebo dôveryhodného režimu
Predvolená výstupná cesta:
build/bench-current.json
Spustenia rozsahových testov zapisujú jeden súbor JSON pre každú množinu údajov a nástroj v priečinku
build/bench-ranges/.
bench:gate porovnáva dva súbory JSON testov výkonu a skončí s nenulovým kódom, ak je niektorá sledovaná metrika pomalšia než nakonfigurovaný limit. Ak nie sú zadané žiadne hodnoty --metric, kontroluje všetky metriky v základnom súbore.
bench:ci je brána na kontrolu regresií výkonu GitHub Actions. Spustí test výkonu všetkých nástrojov s 1k záznamami, porovná vybrané metriky zápisu/čítania/cache/UUID so sledovanou základnou hodnotou bench/baselines/ci-1k-all.json a použije široký predvolený limit, aby zabránila bežnému kolísaniu výkonu runnera a zároveň zachytila veľké regresie výkonu.
bench:jit spúšťa rovnaký testovací rámec so zapnutými CLI opcache a trasovacím JIT a pre proces testu vypína Xdebug, aby PHP mohol skutočne zapnúť JIT.
Vygenerovaný JSON obsahuje príznaky behu, ktoré ukazujú, či boli opcache a JIT počas daného spustenia aktívne.