Tolok Ukur
Harness benchmark menulis JSON yang stabil dan laporan yang mudah dibaca. Lokasinya
ada di bench/ dalam repositori storh dan tidak
lagi menjadi bagian dari paket Composer sejak 0.5.2, jadi perintah composer bench*
di bawah hanya dapat dijalankan dari hasil clone, setelah 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
Hasil referensi
Median dari tiga proses harness penuh, 50,000 record per mesin, pada Apple M1 Pro (16 GB, macOS 26.5, APFS) dengan PHP 8.5 CLI, opcache dan JIT dinonaktifkan:
composer bench:repeat -- --dataset=50000 --engine=all --repeat=3 --memory-limit=512M
Setiap penulisan di-flush dan di-fsync sebelum storh melaporkan bahwa data telah tersimpan, sehingga laju penulisan dibatasi oleh sistem file. Pembacaan dilakukan terhadap cache halaman OS. Laju dihitung dari median; jalankan composer bench dari hasil clone repositori untuk mengukur perangkat keras Anda sendiri.
| DocStore, 50k record | median |
|---|---|
put(), satu file persisten per record |
3.3k record/s |
putStream() ingest massal |
3.7k record/s |
importJsonl() |
3.6k record/s |
get() pembacaan titik, divalidasi STAT |
5.6 µs |
| membuka kembali store yang ada | 0.26 ms |
kueri kesetaraan berindeks, limit(100) |
1.1 ms |
count() berindeks di seluruh koleksi |
41 µs |
| pembangunan indeks, 2 field kesetaraan + 1 field rentang | 52k record/s |
stream() penuh dengan validasi ulang STAT |
103k record/s |
exportJsonl() |
104k record/s |
| SegmentedLog, 50k record, segmen 16 KB | median |
|---|---|
put(), fsync per append |
16k append/s |
appendStream() ingest massal |
56k record/s |
| pembacaan kursor, 100 record dari titik tengah | 2.1 ms |
| pembacaan rentang waktu | 1.1 ms |
count() kesetaraan |
11 µs |
compact() semua segmen tersegel |
69k record/s |
| membuka ulang dengan pemulihan akhir terpotong | 218k record/s |
Benchmark menyegel segmen setiap 16 KB untuk menguji pergantian segmen; ukuran segmen bawaan adalah 1 MiB.
| Queue, 50k pekerjaan | median |
|---|---|
enqueue(), fsync per peristiwa |
22k pekerjaan/s |
claim() |
23k pekerjaan/s |
complete() |
23k pekerjaan/s |
enqueueMany() |
209k pekerjaan/s |
claimMany() |
467k pekerjaan/s |
completeMany() |
512k pekerjaan/s |
| SQL Mirror, SQLite, 50k record | median |
|---|---|
push() awal |
61k baris/s |
push() tanpa perubahan |
86k record/s |
flush(), 100 id |
7.1 ms |
SQL berindeks COUNT di seluruh mirror |
6.9 ms |
rebuild() |
65k baris/s |
restore pull(), satu file persisten per record |
3.2k record/s |
| Mikro | median |
|---|---|
get() yang di-cache, cold lalu warm (MemoryCache, STAT) |
83 µs / 6.3 µs |
| generasi UUIDv7 | 1.3 µs |
| validasi UUIDv7 | 0.30 µs |
| penyaringan predikat dalam memori | 4.4M baris/s |
Target yang dicakup:
- DocStore put, streaming put, ekspor/impor JSONL, get, delete, stream, dan pembangunan indeks
- kueri DocStore dengan indeks kesetaraan, indeks gabungan, indeks rentang, rentang berurutan naik dan turun, hitung terindeks, pencarian ID, dan tanpa indeks
- SegmentedLog append, streaming append, pembacaan kursor, pembacaan rentang waktu, pembacaan rentang waktu hasil pemadatan, pencarian kursor dan ID QueryBuilder, hitung, hitung append massal, statistik, pemadatan
- Queue enqueue, enqueue massal, claim, claim massal, complete, complete massal, requeue
- penyaringan predikat RecordQuery dan QueryCondition pada baris dalam memori
- generasi monotonik UUIDv7, generasi sebaran timestamp, validasi, dan ekstraksi timestamp
- pemulihan baris akhir yang terpotong
- pembacaan cache cold dan warm dengan validasi hash, stat, atau tepercaya
Jalur output bawaan:
build/bench-current.json
Proses rentang menulis satu file JSON per dataset dan mesin di bawah
build/bench-ranges/.
bench:gate membandingkan dua file benchmark JSON dan keluar dengan status non-zero jika metrik yang dipantau mana pun lebih lambat daripada ambang yang dikonfigurasi. Jika tidak ada nilai --metric yang diberikan, semua metrik dalam file baseline akan menjadi pengujian batas.
bench:ci adalah gerbang regresi smoke GitHub Actions. Ini menjalankan benchmark 1k untuk semua mesin, membandingkan metrik tulis/baca/cache/UUID yang dipilih dengan baseline bench/baselines/ci-1k-all.json yang dipantau, dan menggunakan ambang bawaan yang lebar untuk menghindari variasi normal runner sambil tetap menggagalkan regresi kinerja yang besar.
bench:jit menjalankan harness yang sama dengan opcache CLI dan tracing JIT diaktifkan,
serta menonaktifkan Xdebug untuk proses benchmark agar PHP benar-benar dapat mengaktifkan JIT.
JSON yang dihasilkan menyertakan flag runtime yang menunjukkan apakah opcache dan JIT aktif pada proses tersebut.