مقاييس الأداء

مقاييس الأداء (Performance Metrics) هي الأرقام التي تصف مدى سرعة استجابة النظام وكمية العمل التي ينجزها تحت حمل معيّن. وخمسة منها تحمل معظم المعنى: زمن الاستجابة (Response Time)، أي المدة التي يستغرقها طلب واحد كما يراها العميل؛ والكمون (Latency)، أي المدة التي ينتظرها شيء ما أو يقطعها في انتقاله؛ والإنتاجية (Throughput)، أي كمية العمل المنجز في الثانية؛ ومعدل الأخطاء (Error Rate)، أي نسبة العمل الذي يفشل؛ واستخدام الموارد (Resource Utilisation)، أي مدى انشغال المعالج والذاكرة والأقراص والشبكة ومجمّعات الاتصالات.

مثال: واجهة برمجية لإتمام الشراء تستجيب في ⁦290⁩ مللي ثانية عندما يستدعيها مختبِر واحد. وعند ⁦50⁩ طلباً في الثانية قد تبقى استجابتها في حدود ⁦300⁩ مللي ثانية، وقد تستغرق ⁦4⁩ ثوانٍ مع ⁦3%⁩ من الأخطاء بينما تنفد اتصالات قاعدة البيانات. ولا يخبرك أيّ الحالتين حدث ولماذا إلا المقاييس مقيسةً معاً في النافذة الزمنية نفسها.

لماذا يهم

رقم واحد مثل «كان متوسط زمن الاستجابة ⁦400⁩ مللي ثانية» قد يخفي نظاماً يتعثر. فالأخطاء التي تعود بسرعة تخفض المتوسط، وأداة الحمل التي أرسلت حركة أقل من المخطط لها تُظهر النظام سليماً، والخادم الذي بلغ استخدام معالجه ⁦95%⁩ لا يبقى لديه متسع للذروة التالية. وقرارات مثل «هل نطلق الحملة؟» لا تكون أفضل من المقاييس التي بُنيت عليها.

وبالنسبة إلى المختبِر، المقاييس هي اللغة المشتركة مع المطورين وفريق التشغيل ومالك المنتج. فالملاحظة التي تسمّي المقياس، ومكان قياسه، والفترة التي غطّاها، والحمل الذي قيس عنده، يمكن العمل بها؛ أما «النظام بطيء» فلا.

زمن الاستجابة والأجزاء التي يتكوّن منها

زمن الاستجابة هو المدة من لحظة بدء العميل للطلب حتى استلامه الاستجابة كاملة. ويُقاس في جهة العميل، لذا يشمل كل ما في الطريق: العثور على الخادم، وفتح الاتصال، وعمل الخادم نفسه، والنقل في طريق العودة. وكثيراً ما تسجّل سجلات الخادم مدة أقصر لا تشمل الشبكة، لذا اذكر مع كل رقم مكان قياسه.

في اتصال HTTPS جديد ينقسم زمن الاستجابة إلى الأجزاء الأربعة أدناه. وتطبع أداة curl لحظة انتهاء كل جزء عبر الخيار -w؛ والقيم ثوانٍ تُعدّ من البداية، فكل جزء هو الفرق بين قيمتين متجاورتين. ففي المثال يبلغ الانتظار ⁦0.244 − 0.061 = 0.183⁩ ثانية من أصل ⁦0.289⁩ ثانية. فإذا غلب الانتظار فابحث في الخادم، وإذا غلب إنشاء الاتصال فابحث في الشبكة وبُعد الخادم وإعادة استخدام الاتصالات.

  • استعلام DNS: تحويل اسم المضيف إلى عنوان IP.
  • اتصال TCP ومصافحة TLS: فتح الاتصال وتأمينه. والاتصال المُعاد استخدامه (keep-alive) يتخطاهما معاً.
  • الانتظار: ينتقل الطلب إلى الخادم، ويعالجه الخادم، ثم يعود البايت الأول من الاستجابة. ونهاية هذه المرحلة، محسوبةً من البداية، هي زمن وصول البايت الأول (TTFB)؛ أما k6 فيطلق الاسم نفسه على مرحلة الانتظار وحدها.
  • تنزيل المحتوى: وصول بقية الاستجابة. ويطول هذا الجزء مع الجسم الكبير أو غير المضغوط.
fmt='dns=%{time_namelookup} tcp=%{time_connect} tls=%{time_appconnect}'
fmt="$fmt ttfb=%{time_starttransfer} total=%{time_total}\n"
curl -s -o /dev/null -w "$fmt" https://shop.example.com/api/cart

# output in seconds from the start, rounded to milliseconds:
# dns=0.012 tcp=0.030 tls=0.061 ttfb=0.244 total=0.289
طلب HTTPS واحد تقيسه curl: ⁦289⁩ مللي ثانية إجمالاً، منها ⁦61⁩ لإنشاء الاتصال، و⁦183⁩ لانتظار البايت الأول، و⁦45⁩ لتنزيل الجسم.

مخرجات curl -w للطلب GET /api/cart (ثوانٍ من البداية)

الجزء 1:dns=0.012 الجزء 2:tcp=0.030 الجزء 3:tls=0.061 الجزء 4:ttfb=0.244 الجزء 5:total=0.289

  • 1–3إنشاء الاتصال: ⁦61⁩ مللي ثانية قبل إرسال الطلب، وتُتخطى عند إعادة استخدام الاتصال
  • 1–4زمن وصول البايت الأول محسوباً من البداية كما تفعل curl: ⁦244⁩ مللي ثانية (أما TTFB في k6، أي http_req_waiting، فهو الجزء ⁦4⁩ وحده تقريباً)
  • 1–5زمن الاستجابة كما يراه العميل: ⁦289⁩ مللي ثانية
  1. 1استعلام DNSتحويل اسم المضيف إلى عنوان IP؛ والاسم المخزَّن مؤقتاً لا يكاد يكلّف شيئاً.12 ms
  2. 2اتصال TCPرحلة ذهاب وإياب واحدة تفتح الاتصال. والاتصال المُعاد استخدامه يتخطاها.30 - 12 = 18 ms
  3. 3مصافحة TLSتؤمّن الاتصال: رحلة ذهاب وإياب واحدة مع TLS 1.3، وتُتخطى أيضاً عند إعادة الاستخدام.61 - 30 = 31 ms
  4. 4الانتظارينتقل الطلب، ويعمل الخادم، ثم يعود البايت الأول. وبطء شيفرة الخادم يظهر هنا.244 - 61 = 183 ms
  5. 5تنزيل المحتوىوصول بقية الجسم؛ ويطول هذا الجزء مع حجم الاستجابة وبطء الشبكة.289 - 244 = 45 ms

أزمنة توضيحية لطلب واحد على اتصال جديد. تطبع curl ثوانيَ تراكمية من البداية، فكل جزء هو الفرق بين قيمتين متجاورتين.

جرّبها: محلّل زمن الاستجابة جرّبها: محلّل حجم الاستجابة

الكمون: حدّد أيّ معنى تقصد

الكمون (Latency) أكثر المصطلحات تعدّداً في معانيها في مجال الأداء. ففي الشبكات يعني الزمن الذي تستغرقه البيانات في انتقالها، ويُعبَّر عنه عادةً بزمن الذهاب والإياب (Round-Trip Time، RTT). وبعض أدوات الحمل تستخدمه للمدة حتى وصول الجزء الأول من الاستجابة: فمقياس Latency في JMeter يتوقف عند ذلك، بينما يستمر Elapsed time حتى وصول الجزء الأخير. أما الإشارات الذهبية الأربع (Four Golden Signals) في كتاب SRE من Google فتستخدم الكمون للمدة الكاملة لخدمة الطلب، وهي ما يسميه هذا الدرس زمن الاستجابة.

ولهذا الفرق أثر عملي. فاتصال HTTPS الجديد يحتاج إلى نحو ثلاث رحلات ذهاب وإياب قبل وصول البايت الأول: واحدة لمصافحة TCP، وواحدة لمصافحة TLS 1.3، وواحدة للطلب نفسه. ومع RTT قدره ⁦80⁩ مللي ثانية يصبح ذلك نحو ⁦240⁩ مللي ثانية قبل احتساب عمل الخادم، ولا يزيلها خادم أسرع؛ أما إعادة استخدام الاتصال فتزيل رحلتَي إنشاء الاتصال، والخادم الأقرب إلى المستخدمين يقصّر الرحلات الثلاث كلها. كما أن الأدوات تبدأ الساعة وتوقفها عند نقاط مختلفة: فمقياس http_req_duration في k6 هو مجموع الإرسال والانتظار والاستلام، ويُبلغ عن إنشاء اتصال TCP ومصافحة TLS في مقاييس منفصلة، بينما يشملهما time_total في curl. فاكتب في الخطة والتقرير أيّ تعريف يستخدمه كل رقم.

جرّبها: مقارنة أداء API

الإنتاجية ومعدل الأخطاء واستخدام الموارد

زمن الاستجابة يصف الطلبات المفردة. أما المقاييس الثلاثة التالية فتصف النظام تحت الحمل، ولا يكون لها معنى إلا إذا قُرئت معاً، في النافذة الزمنية نفسها، وعند حمل معروف.

  • الإنتاجية (Throughput): العمل المنجز في وحدة الزمن، أي الطلبات في الثانية (RPS)، أو المعاملات في الثانية (TPS) حين يمتد إجراء المستخدم الواحد على عدة طلبات، أو البايتات في الثانية. وهي تَعُدّ ما أنجزه النظام فعلاً، لا ما حاولت أداة الحمل إرساله. وأدوات الحمل مثل JMeter تَعُدّ الطلبات الفاشلة أيضاً ضمن الإنتاجية، فإذا كان الهدف يخص العمل الناجح فاحسب الطلبات الناجحة وحدها. وإذا استمر الحمل في الارتفاع وتوقفت الإنتاجية عن الارتفاع، فقد بلغ النظام حدّاً ما.
  • معدل الأخطاء: عدد الطلبات الفاشلة مقسوماً على جميع الطلبات في النافذة نفسها، كنسبة مئوية. واتفق مع الفريق مسبقاً على ما يُعدّ فشلاً: استجابات 5xx، وانتهاء المهلة، وأخطاء الاتصال، وكذلك، كما ينبّه كتاب SRE، استجابة 200 بمحتوى خاطئ؛ وبعض الفرق تَعُدّ أيضاً، بحكم سياستها، كل استجابة أبطأ من حد متفق عليه فشلاً. وأبلغ عن زمن استجابة الطلبات الناجحة منفصلاً، لأن الأخطاء السريعة تُظهر النظام أسرع مما هو عليه.
  • استخدام الموارد: مدى انشغال كل مورد، أي المعالج والذاكرة والقرص والشبكة والمجمّعات مثل اتصالات قاعدة البيانات وخيوط المعالجة. فالاستخدام يقول كم يُستهلك من المورد، أما التشبّع (Saturation) فيقول هل بدأ العمل يصطف في انتظاره. والمجمّع الذي فيه ⁦50⁩ اتصالاً مستخدماً من أصل ⁦50⁩ مع طلبات تنتظر هو مجمّع متشبّع، مهما أظهر رسم المعالج.
  • مولّد الحمل (Load Generator) مورد أيضاً: فإذا بلغ معالجه أو شبكته الحدّ، فالنتائج تصف الأداة لا النظام قيد الاختبار.

جرّبها: قياس أداء طلبات HTTP

مثال تطبيقي: قراءة تشغيل حمل مدته عشر دقائق

يشغّل فريق عشر دقائق من الحمل الثابت على POST /api/orders في بيئة Staging. والهدف المتفق عليه مع مالك المنتج: ⁦20⁩ طلب شراء ناجحاً في الثانية على الأقل، بمعدل أخطاء أقل من ⁦0.5%⁩. ويجمع الملخص أدناه نتائج أداة الحمل مع لوحات مراقبة الخادم.

من الملخص: إنتاجية الطلبات الناجحة ⁦11,880 / 600 = 19.8⁩ طلباً في الثانية، أي أقل من الهدف بقليل. ومعدل الأخطاء ⁦120 / 12,000 = 1.0%⁩، أي ضعف الحد. والموارد تفسّر السبب: معالج قاعدة البيانات ما زال لديه هامش، لكن مجمّع الاتصالات متشبّع، فتصطف الطلبات في انتظار اتصال حتى تنتهي مهلتها أو تُجيب الخدمة بالرمز 503. والملاحظة التي تُبلَّغ هي «مجمّع الاتصالات مستنفد عند ⁦20⁩ طلباً في الثانية، ومعدل الأخطاء ⁦1.0%⁩» مع إرفاق هذه الأرقام، لا «قاعدة البيانات بطيئة».

POST /api/orders · staging · 10 minutes of steady load

Duration                   600 s
Requests sent              12,000
Successful (201 Created)   11,880
Failed                     120   (84 timeouts after 5 s, 36 x HTTP 503)
Median response time       210 ms (successful requests only)
Database CPU               55% average
DB connection pool         50 of 50 in use, up to 30 requests waiting

المفردات التي ستصادفها

  • المعاملة (Transaction): مجموعة طلبات مسمّاة تُقاس كإجراء مستخدم واحد، مثل «إتمام الشراء»، من أول طلب فيها إلى آخر استجابة.
  • المستخدم الافتراضي (Virtual User، VU): مستخدم واحد محاكى في أداة الحمل، ينفّذ سكربت اختبار (Script) في حلقة متكررة.
  • زمن التفكير (Think Time): التوقف الذي يأخذه المستخدم الحقيقي بين إجراءاته. وإغفاله يجعل ⁦100⁩ مستخدم افتراضي يرسلون حركة أكثر بكثير مما يرسله ⁦100⁩ شخص حقيقي.
  • التزامن (Concurrency): عدد المستخدمين أو الطلبات النشطة في اللحظة نفسها. وهو ليس الإنتاجية: فـ⁦100⁩ مستخدم متزامن قد ينتجون ⁦10⁩ طلبات أو ⁦1,000⁩ طلب في الثانية، بحسب زمن الاستجابة وزمن التفكير.
  • المئين (Percentile)، مثل p95: القيمة التي تقع ⁦95%⁩ من القياسات عندها أو تحتها؛ والوسيط (Median) هو p50، أي القيمة الوسطى. وتعتمد التقارير على المئينات بدلاً من المتوسطات، وللمئينات درس خاص بها.
  • SLI وSLO: مؤشر مستوى الخدمة (SLI) مقياس مُقاس فعلاً، مثل نسبة الطلبات التي أُجيبت خلال ⁦300⁩ مللي ثانية؛ وهدف مستوى الخدمة (SLO) هو القيمة المستهدفة له.
  • الاختناق والهامش (Bottleneck وHeadroom): الاختناق هو المورد الذي يحدّ الإنتاجية أولاً، والهامش هو السعة المتبقية قبل أن يبلغ المورد حدّه.

أخطاء شائعة

  • الإبلاغ عن متوسط واحد لزمن الاستجابة دون ذكر ما إذا كانت الطلبات الفاشلة داخلة فيه.
  • التعامل مع «الكمون» و«زمن الاستجابة» كأنهما رقم واحد، أو مقارنة أداتين تبدأان الساعة وتوقفانها عند نقاط مختلفة.
  • اعتبار الحمل الذي ضُبطت الأداة لإرساله هو الإنتاجية، بدلاً من الطلبات التي أنجزها النظام فعلاً.
  • عدّ استجابات 5xx وحدها أخطاءً، وإغفال انتهاء المهلة وأخطاء الاتصال واستجابات 200 ذات الجسم الخاطئ.
  • الإبلاغ عن أزمنة الاستجابة دون استخدام الموارد، فيقول التقرير «بطيء» ولا يقول أين الحد.
  • القياس من حاسوب محمول على شبكة Wi-Fi، أو من مولّد حمل متشبّع، ثم لوم الخادم على ما أضافته الشبكة أو الأداة.

من منظور ضمان الجودة

اتفق على تعريفات المقاييس قبل أول تشغيل: أيّ المعاملات تُقاس، وأين تبدأ الساعة وأين تتوقف، وما الذي يُعدّ خطأً، وأيّ المئينات والنوافذ الزمنية تُذكر في التقرير، والأهداف المأخوذة من المتطلبات غير الوظيفية. واطلب من المطورين أو فريق التشغيل الوصول إلى لوحات مراقبة الخادم، حتى يُسجَّل استخدام الموارد على الخط الزمني نفسه للحمل. ولا تولّد حملاً إلا على أنظمة تملكها أو لديك إذن مكتوب باختبارها.

وفي التقرير، أعطِ كل رقم سياقه: مستوى الحمل، والمدة، والبيئة، والأداة، وهل قيس في جهة العميل أم في جهة الخادم. واحتفظ بالنتائج الخام حتى يُقارن التشغيل التالي بنظيره. وإذا لم يتحقق هدف ما، فسمِّ المقياس، ومقدار الفارق، والمورد الذي كان متشبّعاً في تلك اللحظة.

تمرين عملي

احسب مقاييس تشغيل لواجهة البحث واحكم عليها

المطلوب

أدناه ملخص تشغيل بحمل ثابت مدته خمس دقائق على GET /api/search في بيئة Staging. ويقول المتطلب: «يتحمّل البحث ⁦40⁩ طلباً في الثانية على الأقل، بمعدل أخطاء أقل من ⁦1%⁩ ووسيط زمن استجابة أقل من ⁦300⁩ مللي ثانية».

احسب المقاييس، وقرّر هل تحقق المتطلب، واكتب الملاحظة التي ستبلّغ عنها والسؤال الذي ستطرحه على الفريق.

المادة
GET /api/search · staging · 300 s steady state · 60 virtual users

Requests sent              13,500
HTTP 200                   13,257  (27 of them with body {"error":"index busy"})
HTTP 504                   135
Client timeouts (3 s)      108
Median response time       180 ms  (all responses, errors included)
App server CPU             92% average, 98% peak
Database CPU               35% average
Load generator CPU         40% average
الخطوات
  1. عُدّ الطلبات الناجحة واحسب إنتاجيتها.
  2. عُدّ كل أنواع الفشل واحسب معدل الأخطاء.
  3. تحقق مما يغطيه وسيط زمن الاستجابة قبل مقارنته بالهدف.
  4. استخدم أرقام الموارد لتحديد موضع الحد.
إظهار الإجابة النموذجية
الإجابة النموذجية

الإنتاجية: ⁦13,257 − 27 = 13,230⁩ طلباً ناجحاً، و⁦13,230 / 300 = 44.1⁩ طلباً في الثانية. فهدف ⁦40⁩ طلباً في الثانية متحقق.

معدل الأخطاء: ⁦135⁩ استجابة 504، و⁦108⁩ حالات انتهاء مهلة، و⁦27⁩ استجابة 200 بجسم خطأ، أي ⁦270⁩ طلباً فاشلاً؛ و⁦270 / 13,500 = 2.0%⁩، أي ضعف حد ⁦1%⁩. فالمتطلب غير متحقق. ولو عُدّت استجابات 504 وحدها لكانت النسبة ⁦1.0%⁩ بالضبط، وهي ما زالت لا تحقق «أقل من ⁦1%⁩»، لكنها تخفي نصف الطلبات الفاشلة.

الوسيط: ⁦180⁩ مللي ثانية أقل من ⁦300⁩، لكنه يخلط الطلبات الفاشلة بالناجحة. فاطلب وسيط الطلبات الناجحة وحدها قبل أن تعدّ هذا الهدف متحققاً.

الحد: يبلغ متوسط استخدام معالج خادم التطبيق ⁦92%⁩ وذروته ⁦98%⁩، بينما لدى قاعدة البيانات هامش (⁦35%⁩)، ومولّد الحمل (⁦40%⁩) ليس هو الاختناق. التقرير: «معدل الأخطاء ⁦2.0%⁩ مقابل حد ⁦1%⁩ عند ⁦44⁩ طلباً في الثانية، ومعالج خادم التطبيق بين ⁦92–98%⁩». واسأل هل لخادم التطبيق في Staging حصة المعالج نفسها التي في بيئة الإنتاج، وماذا تفعل خدمة البحث في كل طلب.

أسئلة شائعة

هل الكمون هو زمن الاستجابة نفسه؟

ليس بالضرورة. زمن الاستجابة هو المدة الكاملة من إرسال الطلب حتى استلام الاستجابة كلها. أما الكمون فقد يعني زمن انتقال البيانات عبر الشبكة، أو المدة حتى البايت الأول، أو في بعض مفردات المراقبة زمن الاستجابة كله. فتحقق من تعريف أداتك واذكر أيّ معنى يمثله كل رقم.

ما زمن الاستجابة الجيد؟

لا يوجد رقم عام. فالهدف يأتي من المتطلبات غير الوظيفية أو من SLO لكل معاملة، مثل مئين معيّن تحت زمن محدد عند حمل محدد. وإذا لم يوجد هدف، فقارن بخط أساس (Baseline) من إصدار سابق.

لماذا الإنتاجية أقل من الحمل الذي ضبطته؟

لأن الإنتاجية تَعُدّ العمل الذي أنجزه النظام. فإذا تباطأت الاستجابات، أرسل كل مستخدم افتراضي ينتظر استجابته طلبات أقل؛ والطلبات التي تنتهي مهلتها لا تكتمل أبداً، والطلبات الفاشلة لا تُحتسب حين تقيس إنتاجية الطلبات الناجحة. والفجوة بين الحمل المضبوط والإنتاجية ملاحظة بحد ذاتها.

المراجع

  • Certified Tester Performance Testing (CT-PT)ISTQB · 2018منهج ISTQB التخصصي لاختبار الأداء: المفاهيم الأساسية وقياسات الأداء وأنشطة الاختبار ومهامه والأدوات.
  • Monitoring Distributed Systems — Site Reliability Engineering (Rob Ewaschuk)Google / O'Reilly Media · 2016إرشادات SRE من Google في المراقبة: المراقبة من الخارج (black-box) مقابل المراقبة من الداخل (white-box)، والإشارات الذهبية الأربع — زمن الاستجابة والحركة والأخطاء والتشبّع.
  • Grafana k6 documentationGrafana Labsالتوثيق الرسمي لأداة Grafana k6، وهي أداة مفتوحة المصدر وقابلة للتوسعة لاختبار الحمل والأداء.
  • Apache JMeter User's ManualApache Software Foundationكيف تُبنى اختبارات الحمل وتُعامَل بالمعاملات وتُشغَّل في JMeter، وكيف تُقرأ مستمعاته وتقاريره.

تدرّب بأدوات متقن

قِس زمن استجابة نقطة نهاية عبر عدة عيّنات: الحد الأدنى والأقصى والمتوسط والوسيط وp95.

الأداء

شغّل قياس أداء صغيراً وآمناً على نقطة نهاية عامة (بعدد طلبات وتزامن محدودَين) واحصل على الإنتاجية ومئينيات زمن الاستجابة.

الأداء

حلّل حجم الاستجابة: البايتات الخام مقابل المضغوطة، وحجم الترويسات، ووزن بنية JSON، وأكبر الحقول.

الأداء

قارن أزمنة الاستجابة والأحجام بين نقطتي نهاية (مثل v1 مقابل v2، أو staging مقابل الإنتاج) جنباً إلى جنب.

الأداء

للتعمّق أكثر

تقدّمك في هذا الموضوع

جزء من مسار تعلم ضمان الجودة