المعايير
تكتب أداة قياس الأداء JSON ثابتة وتقريراً مقروءاً. توجد في bench/ ضمن مستودع storh، ولم تعد جزءاً من حزمة Composer منذ 0.5.2، لذا لا تعمل أوامر composer bench* أدناه إلا من نسخة مستنسخة، بعد 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
النتائج المرجعية
القيم الوسيطة لثلاث عمليات تشغيل كاملة للأداة، بواقع 50,000 سجل لكل محرك، على Apple M1 Pro (ذاكرة 16 GB، وmacOS 26.5، وAPFS) مع PHP 8.5 CLI، وإيقاف opcache وJIT:
composer bench:repeat -- --dataset=50000 --engine=all --repeat=3 --memory-limit=512M
تُفرغ كل كتابة وتُنفذ fsync عليها قبل أن يبلغ storh عن تخزينها، لذا تحدد سرعة الكتابة قدرة نظام الملفات. وتُجرى القراءات من ذاكرة التخزين المؤقت لصفحات نظام التشغيل. اشتُقت المعدلات من القيم الوسيطة؛ شغّل composer bench من نسخة مستنسخة من المستودع على أجهزتك.
| DocStore، 50k سجل | الوسيط |
|---|---|
put()، ملف دائم واحد لكل سجل |
3.3k سجل/ث |
putStream() إدخال جماعي |
3.7k سجل/ث |
importJsonl() |
3.6k سجل/ث |
get() قراءة مفردة، مع التحقق عبر STAT |
5.6 µs |
| إعادة فتح مخزن موجود | 0.26 ms |
استعلام مساواة مفهرس، limit(100) |
1.1 ms |
count() مفهرس عبر المجموعة |
41 µs |
| إنشاء فهرس، حقلا مساواة + حقل نطاق | 52k سجل/ث |
stream() كامل مع إعادة التحقق عبر STAT |
103k سجل/ث |
exportJsonl() |
104k سجل/ث |
| SegmentedLog، 50k سجل، مقاطع بحجم 16 KB | الوسيط |
|---|---|
put()، fsync لكل إضافة |
16k إضافة/ث |
appendStream() إدخال جماعي |
56k سجل/ث |
| قراءة بالمؤشر، 100 سجل من المنتصف | 2.1 ms |
| قراءة ضمن نطاق زمني | 1.1 ms |
count() مساواة |
11 µs |
compact() جميع المقاطع المختومة |
69k سجل/ث |
| إعادة الفتح مع استرداد الذيل المبتور | 218k سجل/ث |
تختم أداة القياس مقطعاً كل 16 KB لاختبار تدوير المقاطع؛ حجم المقطع الافتراضي هو 1 MiB.
| Queue، 50k مهمة | الوسيط |
|---|---|
enqueue()، fsync لكل حدث |
22k مهمة/ث |
claim() |
23k مهمة/ث |
complete() |
23k مهمة/ث |
enqueueMany() |
209k مهمة/ث |
claimMany() |
467k مهمة/ث |
completeMany() |
512k مهمة/ث |
| SQL Mirror، SQLite، 50k سجل | الوسيط |
|---|---|
push() الأولي |
61k صف/ث |
push() دون أي تغييرات |
86k سجل/ث |
flush()، 100 معرّف |
7.1 ms |
SQL COUNT مفهرس على المرآة |
6.9 ms |
rebuild() |
65k صف/ث |
pull() استعادة، ملف دائم واحد لكل سجل |
3.2k سجل/ث |
| مصغر | الوسيط |
|---|---|
get() مخزنة مؤقتاً، باردة ثم دافئة (MemoryCache، STAT) |
83 µs / 6.3 µs |
| إنشاء UUIDv7 | 1.3 µs |
| التحقق من UUIDv7 | 0.30 µs |
| ترشيح المسندات في الذاكرة | 4.4M صف/ث |
العمليات المشمولة:
- DocStore put وstreaming put وJSONL export/import وget وdelete وstream وإنشاء الفهرس
- الاستعلامات المفهرسة بالمساواة والمركبة والنطاق، والنطاق المرتب تصاعدياً وتنازلياً، والعد المفهرس، والبحث بالمعرّف، واستعلامات DocStore غير المفهرسة
- SegmentedLog append وstreaming append وقراءات المؤشر وقراءات النطاق الزمني وقراءات النطاق الزمني بعد الضغط وعمليات بحث المؤشر والمعرّف عبر QueryBuilder والعد وعمليات الإضافة المجمعة والإحصاءات والضغط
- Queue enqueue وbulk enqueue وclaim وbulk claim وcomplete وbulk complete وrequeue
- ترشيح المسندات في RecordQuery وQueryCondition عبر الصفوف الموجودة في الذاكرة
- إنشاء UUIDv7 رتيباً وموزعاً زمنياً والتحقق منه واستخراج الطابع الزمني
- استرداد السطر اللاحق المبتور
- قراءات الذاكرة المؤقتة الباردة والدافئة مع التحقق بالتجزئة أو الإحصاءات أو الثقة
مسار الإخراج الافتراضي:
build/bench-current.json
تكتب عمليات النطاق ملف JSON واحداً لكل مجموعة بيانات ومحرك ضمن build/bench-ranges/.
تقارن bench:gate ملفي JSON لقياس الأداء، وتخرج برمز غير صفري عندما يكون أي مقياس متتبع أبطأ من الحد المُعد. إذا لم تُمرر قيم --metric، فستطبق عتبة القياس على كل مقياس موجود في الملف الأساسي.
bench:ci هو بوابة اختبار الانحدار السريع في GitHub Actions. يشغّل معيارًا لجميع المحركات بحجم 1k، ويقارن مقاييس الكتابة والقراءة والتخزين المؤقت وUUID المحددة بالخط الأساسي المتعقّب bench/baselines/ci-1k-all.json، ويستخدم حدًا افتراضيًا واسعًا لتجنب ضوضاء بيئة التشغيل المعتادة، مع الاستمرار في الإخفاق عند حدوث تراجعات كبيرة في الأداء.
تشغّل bench:jit الأداة نفسها مع تفعيل opcache وJIT التتبعي في CLI، وتعطّل Xdebug لعملية قياس الأداء كي يتمكن PHP فعلياً من تفعيل JIT. يتضمن JSON المُنشأ أعلام وقت التشغيل التي توضح ما إذا كان opcache وJIT نشطين في ذلك التشغيل.