تجيب هذه المقالة على سؤال محدد - كيفية قياس واجهة برمجة التطبيقات الخلفية بطريقة قابلة للتكرار - من خلال توثيق البروتوكول الذي سنطبقه في Aurabase قبل نشر أي أرقام أداء. ليست نتائج: طريقة. يجب التعامل مع أي قياس تم نشره بالفعل في مكان آخر على هذا الموقع (لا سيما على صفحة الخاصة بالأداء) والذي لا يعتمد بالفعل على هذا البروتوكول على أنه لم يتم التحقق منه حتى إشعار آخر.
الأساسيات
لا توجد نتائج لأداء Aurabase بعد بروتوكول منشور قابل للتكرار حتى الآن - توثق هذه المقالة المنهجية التي سنطبقها لإنتاجها، وليس النتائج التي تم الحصول عليها بالفعل. يحتوي المستودع بالفعل على مجموعة اختبار مكونة من 3 مستويات: معايير Criterion.rs الدقيقة على 3 صناديق، واختبارات تحميل k6 على 8 سيناريوهات HTTP/WebSocket، وبرنامج نصي Python لمقارنة Postgres المباشرة مقابل API مع حساب النسبة المئوية. يعتمد البروتوكول الكامل - مدة القياس، والنسب المئوية بدلاً من المتوسطات، وعزل البيئة، والكشف عن الإصدار والتاريخ - على مصادر خارجية تم التحقق منها: PostgreSQL، وCriterion.rs، وk6 (Grafana)، وHdrHistogram، وPlanetScale، وConvex. أي مطالبات بالأداء منشورة بالفعل في مكان آخر على هذا الموقع دون أن يتم تتبعها إلى هذا البروتوكول يجب اعتبارها غير مؤكدة.
لماذا لا ننشر الارقام المجردة
لقد نأت شركة Convex، وهي ناشر واجهة خلفية سريعة الاستجابة، بنفسها علنًا عما يسميه فريقها الفني "حرب المخططات الشريطية" بين موفري قواعد البيانات. صيغته مباشرة: "إنه توسيع نطاق المسرح، وليس توسيع النطاق" - توسيع نطاق المسرح، وليس توسيع النطاق الحقيقي (stack.convex.dev/on-competitive-benchmarks، مدونة Stack التقنية، تم الوصول إليها في 23 أغسطس 2026).
حجتها المركزية: المعيار الذي يقارن نظامين بضمانات مختلفة من حيث الاتساق، أو الهيكل، أو نموذج التسعير في كثير من الأحيان لا يختبر نفس الشيء، حتى عندما يدعي أنه يفعل ذلك - "المعيار لا يختبر في الواقع نفس الشيء". هذا المنعكس له اسم في الصناعة: قياس الأداء، حيث يتم نشر رقم تم اختياره لتأثيره التسويقي وليس لصرامته المنهجية.
ردنا ليس رفض القياس - فرفض نشر رقم إلى أجل غير مسمى سيكون بمثابة عدم أمانة مثل نشر رقم غير مثبت. إنه أولًا توثيق كيفية قياسنا، وبأي أدوات وتحت أي ظروف، قبل الادعاء بأننا قمنا بقياس أي شيء. وهذا أيضًا ما يميز المقارنة المفيدة (مثل مقارنة Aurabase vs Appwrite، التي توثق الاختلافات المعمارية التي يمكن التحقق منها) من مقارنة أرقام الأداء بدون بروتوكول مشترك.
وهذا مهم بشكل خاص بالنسبة للقائد الفني أو كبير مسؤولي التكنولوجيا الذي يجب أن يدافع عن اختيار الواجهة الخلفية في لجنة فنية: الرقم الذي لا يمكن إرجاعه إلى طريقة ما لا ينجو من السؤال الأول المُلح إلى حد ما. البروتوكول الموثق يدافع عن نفسه — يمكنك إظهار البرنامج النصي والنسخة التي تم اختبارها وإجراء الاختبار مرة أخرى أمام شخص ما إذا لزم الأمر.
ما الذي يجعل معظم معايير الواجهة الخلفية مضللة؟
يظهر مأزقان بشكل منهجي: مقارنة الهياكل المختلفة دون الإبلاغ عنها، وقياس زمن الوصول بطريقة تخفي تمامًا فترات التوقف المؤقت التي تهم المستخدم كثيرًا.
فيما يتعلق بالنقطة الأولى، يوثق PlanetScale بوضوح قيود تكافؤ الأجهزة الخاصة به: يجب أن تعمل كل بيئة مقارنة على موارد حوسبة (vCPU، RAM) مساوية أو أكبر من المثيل المرجعي، في نفس منطقة السحابة (Planetscale.com/benchmarks، منهجية "Telescope"، تم الوصول إليها في 23 أغسطس 2026). وبدون هذا الانضباط، قد تعكس فجوة زمن الاستجابة ببساطة جهازًا أكبر - وليس بنية أسرع.
ينطبق نفس المبدأ على حالة ذاكرة التخزين المؤقت وطوبولوجيا الشبكة. يستجيب المثيل الذي بدأ للتو (ذاكرة التخزين المؤقت الباردة لـ Postgres، وتجمع الاتصال الفارغ، وخطة الاستعلام التي لم يتم تخزينها مؤقتًا بعد) بشكل أبطأ من الناحية الهيكلية من المثيل الذي تم تشغيله لمدة ساعة تحت تحميل مستقر. يستجيب الاستعلام من نفس المنطقة حيث تستجيب قاعدة البيانات بشكل أسرع من الاستعلام عبر المناطق. إن المعيارين اللذين لا يحددان أياً منهما لا يمكن مقارنتهما ببساطة، حتى لو كانا يعرضان وحدات متطابقة.
في النقطة الثانية، تسمى المصيدة الإغفال المنسق. HdrHistogram، المشروع المرجعي لقياس زمن الاستجابة الذي أنشأه جيل تيني، يشرح الأمر بهذه الطريقة: عندما ينتظر مولد التحميل استجابة الطلب قبل إرسال الطلب التالي (حلقة مغلقة)، يؤدي إيقاف الخدمة مؤقتًا تلقائيًا إلى تقليل عدد الطلبات المرسلة أثناء التوقف المؤقت - وبالتالي عدد قياسات زمن الوصول العالي المسجلة (github.com/HdrHistogram/HdrHistogram، تم الوصول إليه في 23 أغسطس 2026). يقدم المشروع مثالاً ملموسًا وكميًا: على نظام افتراضي يقوم باختبار زمن الوصول الخاص به كل 10 مللي ثانية لمدة 200 ثانية، فإن توقفًا واحدًا لمدة 100 ثانية في منتصف الاختبار يكفي لإنتاج رسم بياني، بدون تصحيح، حيث يبدو أن 99.99% تقريبًا من الاستجابات تتناسب مع أقل من 1 مللي ثانية - على الرغم من انقضاء نصف الوقت الحقيقي في هذه الإيقاف المؤقت الفردي.
اختبار تحميل الحلقة المغلقة الذي يرسل طلبًا فقط بعد تلقي الاستجابة السابقة بشكل منهجي، يمثل فترات توقف طويلة بشكل ناقص. قد يكون p99 الذي يعرضه أفضل من الواقع الذي يعيشه المستخدم الحقيقي - ليس لأن النظام سريع، ولكن لأن بروتوكول القياس "نسي" إرسال الاستعلامات أثناء التوقف مؤقتًا.
لماذا يكذب المتوسط: ص50، ص95، ص99
قد يبدو متوسط زمن الوصول ممتازًا عندما يستغرق طلب واحد من كل عشرين طلبًا خمسة أضعاف الوقت. وهذا هو بالضبط ما تكشفه النسب المئوية وما يخفيه المتوسط هيكليا.
ميكانيكيًا، لا يوجد شيء غامض بشأن النسبة المئوية: قم بفرز جميع فترات الاستجابة المقاسة بترتيب تصاعدي، ثم خذ القيمة في الموضع المقابل. من بين 1000 استعلام تم فرزه، p50 هي القيمة 500، p95 هي القيمة 950، p99 هي القيمة 990. يكفي طلب واحد بطيء بشكل غير طبيعي من بين 1000 طلب لتحريك p99 - إن حساسيته للحالات النادرة على وجه التحديد هي التي تجعله مفيدًا، حيث لا يكون لهذا الطلب المعزول نفسه أي تأثير تقريبًا على المتوسط.
علامة Telltale: التقرير النصي الذي يعرضه pgbench - أداة قياس أداء PostgreSQL الرسمية - يعرض افتراضيًا متوسطًا وانحرافًا معياريًا ، وليس نسبًا مئوية (postgresql.org/docs/current/pgbench.html، تم الوصول إليه في 23 أغسطس 2026). تحذر وثائقه الرسمية أيضًا: "لا تصدق أبدًا أي اختبار يتم إجراؤه لبضع ثوانٍ فقط" - لا تصدق أبدًا اختبارًا يتم تشغيله لبضع ثوانٍ فقط، وهو ما ينطبق على المدة بقدر ما ينطبق على المقياس المختار.
k6، أداة التحميل التي نستخدمها للمستوى 2 من مجموعتنا، تحل هذه المشكلة من خلال الحدود المعبر عنها بالنسب المئوية: يحدد بناء الجملة p(95)<500 معيار النجاح/الفشل - يجب أن تستجيب 95% من الطلبات خلال 500 مللي ثانية - مباشرة في تكوين الاختبار (grafana.com/docs/k6، تمت استشارته في أغسطس 23, 2026).
| ص50 (متوسط) | نصف الاستعلامات أسرع من هذه القيمة | يخفي ذيل التوزيع تماما |
|---|---|---|
| p95 | 1 من كل 20 استعلامًا يكون أبطأ | المنطقة التي يظهر فيها المستخدمون غير الراضين لأول مرة |
| p99 | 1 من كل 100 استعلام أبطأ | الأكثر حساسية للإغفال المنسق إذا كان البروتوكول مصممًا بشكل سيء |
المستويات القياسية الثلاثة موجودة بالفعل في مستودعنا
إن نشر منهجية دون أدوات حقيقية سيكون مجرد شكل آخر من أشكال المسرح. يحتوي المجلد benchmarks/ الموجود في مستودع Aurabase بالفعل على مجموعة من 3 مستويات، مستوحاة في بنيتها من منهجية Supabase العامة - الأدوات موجودة، والنتائج المقاسة والمؤرخة غير موجودة بعد.
المستوى 1 - المعايير الدقيقة Criterion.rs
تحتوي ثلاثة صناديق من مساحة عمل الشحن على معايير مرتبطة بوحدة المعالجة المركزية (CPU): aura-crypto (تجزئة Argon2، JWT HS256 — الإنشاء والتحقق والتوقيع لتشفير PostgREST وAES-GCM)، aura-db-adapters (تحليل المرشحات وselect بتنسيق PostgREST) — eq., gte., in.(), تضمين العلاقة) و aura-core (تسلسل JSON، دقة schema_name، التحقق من صحة UUID).
يقيس aura-db-adapters على وجه التحديد تكلفة تحليل استعلامات تنسيق PostgREST - أربع حالات للمرشحات (simple_4, complex_10, or_group, in_large_50 مع 50 قيمة) وأربع حالات لـ select (أعمدة فردية، *، علاقة واحدة مضمنة، وخمسة تضمينات). هذا هو نوع التكلفة غير المرئي في اختبار التحميل العالمي: الانحدار في تحليل مرشح or.(...) المعقد لن يغير شيئًا تقريبًا في p95 لنقطة نهاية قليلة الاستخدام، ولكنه سيصبح قابلاً للقياس على نقطة نهاية ذات حركة مرور عالية - ومن هنا الاهتمام بعزله في معيار صغير بدلاً من الاعتماد فقط على المستوى 2.
يتبع aura-core نهجًا مختلفًا: بدلاً من قياس الوقت الخام، فإنه يقيس الإنتاجية (Throughput::Bytes) على تسلسل JSON وإلغاء تسلسل رسائل NatsRequest/NatsResponse الداخلية المتبادلة بين البوابة والخدمات - مع ثلاثة أحجام حمولة واقعية (حد أدنى من الطلب، طلب مع نص JSON متداخل، قائمة مكونة من 50 سطرًا استجابة).
Criterion.rs لا يقتصر على تكرار الحلقة. يقوم أولاً بتشغيل مرحلة إحماء لملء ذاكرة التخزين المؤقت لوحدة المعالجة المركزية/نظام التشغيل، ويكتشف القيم المتطرفة بنسخة معدلة من طريقة Tukey (دون استبعادها من مجموعة البيانات)، ويحسب فترات الثقة عن طريق التمهيد على عدد كبير من العينات المعاد تشكيلها، ويكتشف تراجعات الأداء بين عمليتي تشغيل بواسطة الاختبار الإحصائي للطالب، مع حد ضوضاء قابل للتكوين - عادةً ±1% - لتجاهل الاختلافات التي ليست ذات دلالة إحصائية (bheisler.github.io/criterion.rs/book/analogy.html، تم الوصول إليه في 23 أغسطس 2026).
يقوم كل تشغيل للمعيار بإنشاء تقرير HTML مفصل في target/criterion/ — التوزيعات ورسومات الانحدار والمقارنة بالتشغيل السابق. إن هذه العلاقة، وليس مجرد خط نهائي، هي التي يجب على المنهجية الجادة أن تجعل من الممكن تجديدها.
المستوى 2 - اختبار الحمل k6
تغطي ثمانية نصوص k6 بوابة على جانب مستوى البيانات: health (خط الأساس لزمن الوصول)، auth-flow (التسجيل ← تسجيل الدخول ← تحديث ← تسجيل الخروج)، crud-read و crud-write, storage (تحميل/تنزيل)، realtime-ws, breakpoint (زيادة الحمل حتى الفشل) و supabase-compare. تم توصيل سبعة منها بهدف Makefile مخصص - supabase-compare.js موجود في المستودع ولكن ليس لديه هدف بعد، وهي حالة توثقها هذه المقالة كما هي بدلاً من إخفائها.
يحدد التكوين المشترك الحدود لكل نوع عملية. هذه هي معايير النجاح/الرسوب التي يتحقق منها الاختبار في كل مرة يتم تشغيلها - وليست النتائج التي تم قياسها بالفعل:
| القراءة (الحصول على) | p95 <500 مللي ثانية · p99 <1000 مللي ثانية | التكوين k6 (المعايير/k6/lib/config.js) |
|---|---|---|
| الكتابة (ما بعد/التصحيح) | p95 <300 مللي ثانية · p99 <1000 مللي ثانية | التكوين k6 |
| المصادقة (تسجيل الدخول/التحديث) | p95 <300 مللي ثانية · p99 <1000 مللي ثانية | التكوين k6 |
| التخزين (تحميل/تنزيل) | p95 <500 مللي ثانية · p99 <2000 مللي ثانية | التكوين k6 |
| معدل الخطأ، جميع السيناريوهات | < 1 % | التكوين k6 |
يوثق README.md الموجود في المجلد benchmarks/ عتبة قراءة تبلغ p95 عند < 200ms ("Supabase SLO")، بينما العتبة المطبقة فعليًا في benchmarks/k6/lib/config.js - التي يتم تشغيلها بالاختبار - هي p(95)<500. الملفان مشتقان من بعضهما البعض. هذا مثال ملموس، تم العثور عليه أثناء قراءة الكود المصدري لهذه المقالة، لماذا يجب أن يكون للبروتوكول مصدر واحد للحقيقة بدلاً من توثيقه في مكانين: بدونه، حتى الفريق الذي يحاول أن يكون صارمًا ينتهي به الأمر إلى نشر عتبات متعارضة.
المستوى 3 - المقارنة المباشرة بين PostgreSQL وAPI
يقوم برنامج Python النصي (direct_vs_api.py) بقياس الحمل الفعلي للبوابة + طبقة الخدمة من خلال مقارنة طلبات psycopg2 المباشرة باستدعاءات HTTP في نفس العملية - قائمة، قراءة لمرة واحدة حسب المعرف، قراءة تمت تصفيتها وفرزها. يتبع كل قياس إحماء 10 تكرارات قبل الحلقة الموقوتة، ثم يحسب المتوسط، p50، p95، p99 والإنتاجية في العمليات في الثانية.
يطبق البرنامج النصي الثاني (aurabase_vs_supabase.py) نفس منطق الحساب المئوي والإحماء على المقارنة المباشرة مع مثيل Supabase المحلي (Supabase CLI، localhost:54321 افتراضيًا) - نفس الجهاز، نفس الشبكة المحلية لكليهما، بالضبط نظام تكافؤ البيئة الذي يوثقه PlanetScale لإجراء مقارناته الخاصة.
يربط البرنامج النصي للتنسيق (collect_baseline.sh، الهدف bench-baseline من Makefile) المستويات الثلاثة - المعيار على الصناديق الثلاثة، ومجموعة فرعية من سيناريوهات k6 (health و crud-read اليوم، وليس كل 8 حتى الآن)، ثم مقارنة Python - ويكتب السجلات، ويقدم JSON و Criterion HTML تقارير إلى مجلد ذو طابع زمني فريد: benchmarks/results/AAAAMMJJ_HHMMSS/. وهذا هو بالضبط انعكاس الكشف المؤرخ، في تشغيل واحد قابل للتكرار، والذي يضفي عليه القسم التالي طابعًا رسميًا في بروتوكول كامل.
البروتوكول الذي سنطبقه قبل نشر الشكل
ثمانية التزامات، كل منها يرتكز على ممارسة تم توثيقها بالفعل بواسطة أداة أو مشروع معترف به تابع لجهة خارجية - ولم يتم اختراعها لهذه المناسبة.
- التسخين منفصل عن القياس. Criterion.rs يملأ ذاكرة التخزين المؤقت لوحدة المعالجة المركزية/نظام التشغيل قبل التوقيت؛
pgbenchتوصي صراحةً بعدم الاعتقاد مطلقًا بأن الجري يستمر لبضع ثوانٍ فقط. - مدة ثابتة، وليس عدد محدد من التكرارات. يحتاج الحمل إلى وقت للتقارب - هذا هو دور
stagesk6 وعلم-Tلـpgbench. - النسب المئوية، وليس فقط المتوسط - واليقظة النشطة بشأن الإغفال المنسق إذا كان مولد الحمل يعمل في حلقة مغلقة.
- البيئة موثقة بالتفصيل: تم اختبار التزام git بالخدمة، وإصدار PostgreSQL، ومواصفات الأجهزة، وإصدار أداة التحميل. يقوم PlanetScale بتوثيق معلمات TPCC الدقيقة (
TABLES=20,SCALE=250, ~500 جيجابايت) لهذا السبب بالتحديد - بدون هذه التفاصيل، لا يمكن لأحد إعادة التشغيل. - نتائج ذات طابع زمني وإصدارات، لا يوجد رقم واحد محفور على صفحة تسويق بدون تاريخ. الأدوات الحالية مكتوبة بالفعل في ملف مؤرخ؛ سيكون من الضروري توسيع هذا المنعكس ليشمل أي قياس منشور علنًا، مع توثيق المنطقة المضيفة مثل أي متغير بيئي آخر (راجع دليلنا حول سيادة استضافة الاتحاد الأوروبي، ذات الصلة بمجرد أن يعتمد الرقم على منطقة معينة).
- يتم نشر البرامج النصية والبيانات الأولية بجانب النتيجة الإجمالية، وليس فقط المتوسط النهائي. بل إن PlanetScale يدعو القراء إلى الإبلاغ عن خطأ منهجي في عنوان مخصص - وهو الموقف الذي نجده صحيًا ونريد استئنافه.
- الإنتاجية المعلن عنها جنبًا إلى جنب مع زمن الوصول، وليس فقط أحدهما أو الآخر. يمكن أن يتمتع النظام بزمن انتقال ممتاز عند التحميل المنخفض وينهار في الإنتاجية مع زيادة التزامن - وهذا هو بالضبط ما تم تصميم سيناريو
breakpointالخاص بمجموعة k6 (القياس إلى التعطل) للكشف عنه، وما يلتقطه قياس المعيار الدقيقThroughput::Bytesالخاص بـ Criterion على مستوى الوظيفة. - فجوة كبيرة قبل الإعلان عن التحسن. قد يكون الاختلاف بنسبة قليلة بين عمليتي تشغيل ضجيجًا في القياس وليس مكسبًا حقيقيًا - يحسب Criterion.rs احتمال أن يكون الاختلاف الملحوظ ناتجًا عن الصدفة قبل تأهيله على أنه تراجع أو تحسن. إن الرقم المعزول، دون هذا التحقق، هو مجرد حكاية إحصائية.
ما لن نفعله
هذه القائمة لها نفس أهمية البروتوكول الإيجابي أعلاه.
- مقارنة الطبولوجيا المختلفة (المثيلات المستضافة ذاتيًا مقابل المُدارة، والمثيلات الباردة مقابل المُسخنة مسبقًا) دون الإبلاغ عنها بشكل صريح.
- احتفظ بأفضل نتيجة من أصل عشرة دون ذكر التسعة الأخرى.
- نشر رقم بدون تاريخ، بدون نسخة خدمة، بدون نص نسخ.
- إعادة نشر رقم تسويقي موجود طالما لم يتم إرجاعه إلى هذا البروتوكول.
- مقارنة أنفسنا بمنافس بناءً على رقم أداء أولي إذا لم ينشر هذا المنافس منهجيته الخاصة بطريقة معادلة - الرقم مقابل الصمت ليس مقارنة، إنه شعار.
تم تعميم رقم مثل "البداية الباردة أقل من 1 مللي ثانية" دون أن يكون مدعومًا بمعيار قابل للتكرار. يتم التعامل معها الآن داخليًا على أنها غير مدعومة ولا يجب قراءتها كخاصية مُقاسة للمنتج حتى يؤكدها أي قياس مؤرخ، باستخدام منهجية منشورة. هذا هو بالضبط نوع الادعاء بأن هذا البروتوكول موجود لمنع تكراره.
الحد الأدنى من البروتوكول لقياس أي واجهة خلفية
لا يعتمد هذا البروتوكول على أي أداة محددة من أدوات Aurabase — يمكنك تطبيقه على واجهة برمجة التطبيقات (API) الخاصة بك اليوم.
- اضبط التحميل قبل الأداة: مزيج واقعي للقراءة فقط والكتابة لتطبيقك - وليس نسبة عامة منسوخة من مشروع آخر.
- افصل بوضوح مرحلة التسخين المسبق عن مرحلة القياس.
- قم بإجراء الاختبار لمدة كافية - دقائق، وليس ثواني.
- قم بالقياس بالنسب المئوية (ص50/ص95/ص99)، وليس في المتوسط وحده.
- تأكد من أن مولد الحمل الخاص بك ليس في حلقة مغلقة، أو قم بتصحيح إغفال التنسيق في التحليل.
- عزل البيئة قيد الاختبار - لا يوجد جيران مزعجون ولا توجد مهام خلفية متنافسة.
- قم بنشر الإصدار الذي تم اختباره والتاريخ ومواصفات الأجهزة والبرنامج النصي - وليس فقط النتيجة النهائية.
على قاعدة Postgres المجردة، يأخذ هذا البروتوكول أمرًا واحدًا pgbench — 20 عميلًا متزامنًا موزعين على 4 سلاسل رسائل، لمدة 5 دقائق، مع تقرير مرحلي كل 10 ثوانٍ:
الأدوات المرجعية، حسب المستوى
خمس أدوات، كل منها مناسبة لمستوى مختلف من المكدس - لا شيء يحل محل الأدوات الأخرى.
| الميكروفون (الوظيفة) | Criterion.rs | وحدة المعالجة المركزية النقية، إحصائيات التمهيد |
|---|---|---|
| استعلام SQL | com.pgbench | المعاملات الشبيهة بـ TPC-B وtps وزمن الوصول |
| تحميل HTTP/WS | ك6 (جرافانا) | النسب المئوية، عتبات النجاح/الفشل |
| OLTP على نطاق واسع | sysbench + TPCC (منهجية التلسكوب) | QPS، التكلفة لكل أداء |
| تصحيح القياس | نطاق عالي الديناميكية الرسم البياني | يعوض عن الإغفال المنسق |