Preskočiť na obsah

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:

Shell
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:

Shell
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:

Text
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.