تعلم طرق Brendan Gregg العملية (USE، RED، مخططات اللهب) للتحقيق في الكمون واختناقات الإنتاج بأدلة بدل التخمين.

يُعد Brendan Gregg من أكثر الأصوات تأثيراً في مجال أداء الأنظمة، خصوصاً في عالم لينكس. كتب كتباً مستخدمة على نطاق واسع، بنى أدوات عملية، والأهم من ذلك — شارك طرقاً واضحة للتحقيق في مشاكل الإنتاج الحقيقية. تعتمد الفرق على طريقته لأنها تعمل تحت الضغط: عندما يرتفع الكمون والجميع يريد إجابات، تحتاج إلى طريقة للتحول من "ربما السبب X" إلى "بالتأكيد Y" بأدلة قليلة وخطوات محددة.
منهجية الأداء ليست أداة واحدة ذكية أو أمر مميز. إنها طريقة قابلة للتكرار للتحقيق: قائمة تحقّق لما تنظر إليه أولاً، كيفية تفسير ما تراه، وكيف تقرر الخطوة التالية.
تلك القابلية للتكرار هي ما يقلل التخمين. بدلاً من الاعتماد على صاحب الحدس الأكبر (أو الصوت الأعلى)، تتبع عملية متسقة تقوم على:
تفشل العديد من تحقيقات الكمون خلال الدقائق الخمس الأولى. يقفز الناس مباشرة إلى الإصلاحات: "أضف CPU"، "أعد تشغيل الخدمة"، "زيد الكاش"، "اضبط GC"، "لا بد أن المشكلة في الشبكة". أحياناً تساعد تلك الإجراءات — وغالباً ما تُخفِي الإشارة، تهدر الوقت، أو تدخل مخاطر جديدة.
تدفعك طرق Gregg إلى تأجيل "الحلول" حتى تستطيع الإجابة على أسئلة أبسط: ما المشبع؟ ما الذي يخطئ؟ ما الذي أصبح أبطأ — الإنتاجية، الطوابير، أم العمليات الفردية؟
يساعدك هذا الدليل على تضييق النطاق، قياس الإشارات الصحيحة، وتأكيد الاختناق قبل التحسين. الهدف هو سير عمل منظم للتحقيق في مشاكل الكمون وبروفايلينغ في الإنتاج بحيث لا تعتمد النتائج على الحظ.
الكمون هو عرض: المستخدمون ينتظرون أطول لإنهاء العمل. السبب عادةً يكون في مكان آخر — تداخل وحدة المعالجة، انتظار القرص أو الشبكة، تداخل الأقفال، جمع القمامة، الطوابير، أو تأخر تبعيات بعيدة. قياس الكمون بمفرده يخبرك أن هناك ألماً، لكنه لا يخبرك من أين ينبع.
تتصل هذه الإشارات الثلاثة ببعضها:
قبل الضبط، اجمع الثلاثة لنفس نافذة الزمن. وإلا فقد "تحل" الكمون عن طريق إسقاط العمل أو الفشل بشكل أسرع.
المتوسط يخفي الذروات التي يتذكرها المستخدمون. خدمة بمعدل متوسط 50 ملليثانية قد تعاني من توقفات متكررة تصل إلى ثانيتين.
تتبع المئينات:
راقب أيضاً شكل الكمون: p50 ثابت مع ارتفاع p99 غالباً ما يشير إلى توقفات متقطعة (مثل تداخل الأقفال، هزات I/O، أو توقفات جمع القمامة) بدل تباطؤ عام.
ميزانية الكمون نموذج محاسبي بسيط: "إذا يجب أن ينتهي الطلب في 300 ملليثانية، كيف يُسمح باستخدام الوقت؟" قسمه إلى دلاء مثل:
تؤطر هذه الميزانية مهمة القياس الأولى: حدد أي دلو نما أثناء الذروة، ثم حقق في ذلك المجال بدلاً من الضبط الأعمى.
يتعثر عمل الكمون عندما يوصف "النظام بطيء". تبدأ طرق Gregg أبكر: حوّل المشكلة إلى سؤال محدد وقابل للاختبار.
اكتب جملتين قبل أن تلمس أي أدوات:
يمنعك هذا من تحسين الطبقة الخطأ — مثل CPU المضيف — حين يكون الألم معزولاً لنقطة نهاية أو تبعية واحدة.
اختر نافذة تطابق الشكوى وتتضمن فترة مقارنة "جيدة" إن أمكن.
حدّد نطاق تحقيقك صراحةً:
الدقة هنا تجعل الخطوات التالية (USE، RED، البروفايلينغ) أسرع لأنك ستعرف أي البيانات ينبغي أن تتغير إذا كانت فرضيتك صحيحة.
دون عمليات النشر، تغييرات التهيئة، تحولات الحركة، وأحداث البُنية التحتية — لكن لا تفترض السببية. كتبها كـ "إذا X، فنحن نتوقع Y" حتى تؤكد أو ترفض بسرعة.
سجل صغير يمنع العمل المكرر بين الزملاء ويسهّل التسليم.
Time | Question | Scope | Data checked | Result | Next step
حتى خمس سطور كهذه يمكن أن تحول حادثاً متوتّراً إلى عملية قابلة للتكرار.
طريقة USE (الاستفادة، التشبع، الأخطاء) هي قائمة فحص سريعة لGregg لمسح "الأربعة الكبار" — CPU، الذاكرة، القرص (التخزين)، والشبكة — لتضييق المشكلة بدلاً من التخمين.
بدلاً من التحديق في عشرات اللوحات، اطرح نفس الأسئلة الثلاثة لكل مورد:
تطبيق هذا باستمرار يصبح جرداً سريعاً لمكان وجود "الضغط".
لـ CPU، الاستفادة هي نسبة انشغال CPU، التشبع يظهر كضغط صف التشغيل أو خيوط تنتظر للتشغيل، والأخطاء قد تشمل تحديد السرعة (throttling) في الحاويات أو مقاطعات سيئة.
لـ الذاكرة، الاستفادة هي الذاكرة المستخدمة، التشبع يظهر غالباً كطَبع صفحات أو جمع قمامة متكرر، والأخطاء تشمل فشل التخصيص أو أحداث OOM.
لـ القرص، الاستفادة هي زمن انشغال الجهاز، التشبع هو عمق الطابور وزمن انتظار القراءة/الكتابة، والأخطاء هي أخطاء I/O أو مهلات.
لـ الشبكة، الاستفادة هي الإنتاجية، التشبع هو السقوط/الطوابير/الكمون، والأخطاء هي إعادة الإرسال، إعادة التعيين، أو فقد الحزم.
عندما يبلغ المستخدمون عن البطء، غالباً ما تكون إشارات التشبع هي الأكثر كشفاً: الطوابير ووقت الانتظار والتداخل تميل إلى الارتباط بالكمون أكثر من الاستفادة الخام.
مقاييس مستوى الخدمة (مثل زمن الطلب ومعدل الأخطاء) تخبرك التأثير. USE يخبرك أين تنظر بعد ذلك بتحديد المورد المتعرض للضغط.
حلقة عملية:
طريقة RED تُبقيك مترسخاً بتجربة المستخدم قبل الغوص في رسوم المضيف.
تمنعك RED من مطاردة مقاييس نظام "مثيرة" لا تؤثر على المستخدمين. تُجبر حلقة أقصر: أي نقطة نهاية بطيئة، لأي مستخدمين، ومنذ متى؟ إذا ارتفعت Duration على مسار واحد بينما CPU الكلي ثابت، فهناك نقطة بداية أوضح.
عادةً ما تكون عادة مفيدة: حافظ على RED مُقسَّمة حسب الخدمة وأهم النقاط النهائية (أو طرق RPC الأساسية). يجعل هذا التفرقة بين تدهور شامل وانتكاسة محلية أسهل.
RED يخبرك أين الألم. USE يساعدك على اختبار أي مورد مسؤول.
أمثلة:
حافظ على تخطيط مركز:
إذا أردت سير حادث متسق، اقترن هذا الجزء مع جرد USE في /blog/use-method-overview حتى تتحرك من "المستخدمون يشعرون بالأمر" إلى "هذا المورد هو القيد" مع ضوضاء أقل.
يمكن أن يتفجر تحقيق الأداء إلى عشرات الرسوم والفرضيات خلال دقائق. عقلية Gregg هي إبقاؤها ضيقة: عملك ليس "جمع المزيد من البيانات"، بل طرح السؤال التالي الذي يقضي على أكبر قدر من اللايقين بسرعة.
معظم مشاكل الكمون يهيمن عليها تكلفة واحدة (أو زوج صغير): قفل ساخن، تبعية بطيئة، قرص مثقل، نمط توقف GC. تعني الأولويات البحث عن تلك التكلفة المسيطرة أولاً، لأن تقليم 5% من خمسة أماكن نادراً ما يحرك الكمون المرئي للمستخدم.
اختبار عملي: "ما الذي قد يفسر معظم التغير في الكمون الذي نراه؟" إذا كانت فرضية لا تفسّر سوى جزء ضئيل، فهي أولوية أدنى.
استخدم من الأعلى إلى الأسفل عند الإجابة على "هل المستخدمون متأثرون؟" ابدأ من النقاط النهائية (إشارات على نمط RED): الكمون، الإنتاجية، الأخطاء. هذا يساعدك على تجنّب تحسين شيء ليس في المسار الحرج.
استخدم من الأسفل إلى الأعلى عندما يكون المضيف مريضاً بوضوح (أعراض USE): تشبع CPU، ضغط ذاكرة، انتظار I/O. إذا كانت العقدة محمّلة، ستضيع وقتك في مراقبة مئينات النقاط النهائية دون فهم القيد.
عندما يرن تنبيه، اختر فرعاً وابقَ عليه حتى تؤكده أو تنفيه:
حدّد لنفسك مجموعة صغيرة من الإشارات الابتدائية، ثم توغّل فقط عندما يتحرك شيء. إذا احتجت قائمة تحقق للحفاظ على التركيز، اربط خطواتك بدليل تشغيل مثل /blog/performance-incident-workflow حتى يكون لكل مقياس هدف محدد: الإجابة على سؤال معين.
قد يبدو بروفايلينغ الإنتاج مخاطرة لأنه يلمس النظام الحي — لكنه غالباً أسرع طريقة لاستبدال الجدل بالأدلة. السجلات واللوحات يمكن أن تخبرك بأن شيئاً ما بطيء. البروفايلينغ يخبرك أين يذهب الوقت: أي الدوال تعمل بكثافة، أي الخيوط تنتظر، وما مسارات الكود التي تهيمن أثناء الحادث.
البروفايلينغ أداة "ميزانية وقت". بدلاً من مناقشة النظريات ("هي قاعدة البيانات" مقابل "هو GC"), تحصل على دلائل مثل "45% من عينات CPU في تحليل JSON" أو "معظم الطلبات محجوزة على mutex". هذا يضيق الخطوة التالية إلى إصلاح أو اثنين محددين.
كل واحد يجيب عن سؤال مختلف. الكمون العالي مع CPU منخفض غالباً ما يشير إلى وقت خارج-CPU أو وقت قفل بدلًا من نقاط ساخنة CPU.
تبدأ الفرق غالباً عند الطلب، ثم تنتقل إلى دائم التشغيل عندما تثق بالسلامة وترى مشكلات متكررة.
بروفايل آمن للإنتاج يعني التحكم بالتكلفة. فضّل العينة (sampling) بدل تتبّع كل حدث، اجعل نوافذ الالتقاط قصيرة (مثلاً 10–30 ثانية)، وقيّم العبء أولاً في كاناري. إن لم تكن متأكداً، ابدأ بعينات منخفضة التردد وزدها فقط إذا كان الإشارة متوسطة الضوضاء.
مخططات اللهب تجعل وقت العينة المرئية خلال نافذة البروفايل. كل "مربع" هو دالة (أو إطار مكدس)، وكل مكدس يظهر كيف وصلت التنفيذ إلى تلك الدالة. ممتازة لاكتشاف الأنماط بسرعة — لكنها لا تخبرك تلقائياً "الخلل هنا".
عادةً ما تمثل مخططات اللهب عينات على-CPU: الوقت الذي كان البرنامج فعلياً يعمل على نواة CPU. يمكن أن تُبرز مسارات كود تستهلك CPU بكثافة، تحليل غير فعال، تسلسل زائد، أو نقاط ساخنة تحرق CPU.
لا تُظهر مباشرة الانتظار على القرص أو الشبكة أو تأخيرات المجدول، أو وقت الحجز على mutex (هذا وقت خارج-CPU ويحتاج بروفايل مختلف). كما أنها لا تثبت السببية لزمن استجابة المستخدم ما لم تربطها بسؤال محدد.
الصندوق الأعرض مغرّ للوم، لكن اسأل: هل هذه نقطة ساخنة يمكنك تغييرها، أم مجرد "وقت في malloc، GC، أو التسجيل" لأن المشكلة الحقيقية تكون في مصدر أعلى؟ راقب أيضاً السياق المفقود (JIT، inline، الرموز) الذي قد يجعل صندوقاً يبدو كالمذنب بينما هو مجرد رسول.
عامل مخطط اللهب كإجابة لسؤال محدود: أي نقطة نهاية، أي نافذة زمنية، أي خوادم، وما الذي تغير. قارن مخططات "قبل مقابل بعد" (أو "صحي مقابل متدهور") لنفس مسار الطلب لتجنب ضوضاء البروفايل.
عند قفز الكمون، تنظر العديد من الفرق إلى نسبة CPU أولاً. هذا مفهوم — لكنه غالباً ما يوجهك في الاتجاه الخاطئ. يمكن أن تكون الخدمة "تستخدم 20% CPU فقط" وما تزال بطيئة لأن خيوطها تمضي معظم وقتها غير قيد التشغيل.
%CPU يجيب على "كم المعالج مشغول؟" لكنه لا يجيب على "أين ذهب وقت طلبي؟" قد تتعطل الطلبات بينما الخيوط تنتظر أو تُوقَف أو تُركَن من قبل المجدول.
فكرة أساسية: وقت الحائط لطلب يشمل العمل على-CPU ووقت الانتظار خارج-CPU.
وقت خارج-CPU يختبئ عادة وراء التبعيات والتداخل:
بعض الإشارات غالباً ما ترتبط باختناقات خارج-CPU:
تخبرك هذه الأعراض "ننتظر"، لكنها لا تخبرك على ماذا ننتظر.
ينسب بروفايل خارج-CPU الوقت إلى سبب عدم تشغيلنا: الحجز في نداءات النظام، الانتظار على أقفال، النوم، أو النزع من المجدول. ذلك قوي لعمل الكمون لأنه يحول التباطؤ الغامض إلى فئات قابلة للعمل: "محجوز على mutex X"، "ينتظر read() من القرص"، أو "معلق في connect() لتبعٍ بعيد". بمجرد أن تسمي الانتظار، يمكنك قياسه، تأكيده، وإصلاحه.
غالباً ما يفشل عمل الأداء في نفس اللحظة: يلمح شخص ما مقياساً مشبوهاً، يعلنه "المشكلة"، ويبدأ الضبط. تدفعك طرق Gregg إلى التريث وإثبات ما يحد النظام قبل تغيير أي شيء.
الاختناق هو المورد أو المكوّن الذي حالياً يحد الإنتاجية أو يزيد الكمون. إذا خففته، سيرى المستخدمون تحسناً.
النقطة الساخنة هي حيث يُنفق الوقت (مثلاً دالة تظهر كثيراً في بروفايل). النقاط الساخنة قد تكون اختناقات حقيقية — أو مجرد عمل مشغول لا يؤثر على المسار البطيء.
الضوضاء هو كل ما يبدو مهمّاً لكنه ليس كذلك: وظائف خلفية، ذروات لمرة واحدة، آثار العينة، تأثيرات الكاش، أو "المتكلمون الكبار" الذين لا يرتبطون بالمشكلة المرئية للمستخدم.
ابدأ بالتقاط لقطة "قبل" نظيفة: العَرَض المواجه للمستخدم (الكمون أو معدل الأخطاء) والإشارات المرشحة (تشبع CPU، عمق الطابور، I/O للقرص، تداخل الأقفال، إلخ). ثم طبق تغييراً متحكَّماً يجب أن يؤثر فقط على السبب المشتبه فيه.
أمثلة لاختبارات سببية:
الارتباط تلميح، وليس حكم. إذا "CPU يرتفع عندما يرتفع الكمون"، فأكد بتغيير توفر CPU أو تقليل العمل على CPU وملاحظة إن تبع الكمون التغيير.
دوّن: ما الذي قستَه، التغيير الدقيق الذي أُجري، نتائج قبل/بعد، والتحسن الملاحظ. هذا يحول الفوز مرة واحدة إلى خطة قابلة لإعادة الاستخدام للحادث القادم — ويمنع "الحدس" من إعادة كتابة التاريخ لاحقاً.
حوادث الأداء تبدو عاجلة، وهذا بالذات الوقت الذي يتسلل فيه التخمين. سير عمل خفيف وقابل للتكرار يساعدك على الانتقال من "شيء ما بطيء" إلى "نعلم ما تغير" دون ارتجال.
كشف: إنذار على الكمون المرئي للمستخدم ومعدل الأخطاء، لا فقط CPU. أنبِه عند عبور p95/p99 عتبة لفترة مستمرة.
تصنيف: أجب فوراً عن ثلاثة أسئلة: ما الذي بطيء، متى بدأ، ومن المتأثر؟ إذا لم تستطع تسمية النطاق (خدمة، نقطة نهاية، منطقة، شريحة)، فأنت لست جاهزاً للتحسين.
قياس: اجمع أدلة تضيق الاختناق. فضّل الالتقاطات محدودة الزمن (مثلاً 60–180 ثانية) حتى تتمكن من المقارنة "السيء" مقابل "الجيد".
إصلاح: غيِّر شيئاً واحداً في كل مرة، ثم أعد قياس نفس الإشارات لتأكيد التحسن واستبعاد الدواء الوهمي.
حافظ على لوحة مشتركة يستخدمها الجميع أثناء الحوادث. اجعلها مملة ومتسقة:
الهدف ليس رسم كل شيء؛ الهدف تقصير زمن الوصول إلى أول حقيقة.
قم بقياس النقاط النهائية الأكثر أهمية (checkout، تسجيل الدخول، البحث)، لا كل نقطة. لكل منها اتفق على: p95 المتوقع، أقصى معدل خطأ، والتبعية الرئيسية (DB، الكاش، طرف ثالث).
قبل الخروج للتعطل التالي، اتفق على مجموعة التقاط:
وثّقها في دليل تشغيل قصير (مثلاً /runbooks/latency)، بما في ذلك من يمكنه تشغيل الالتقاطات وأين تُخزن الآثار.
منهجية Gregg تدور حول التغيير المتحكم والتحقق السريع. إذا كان فريقك يبني خدمات باستخدام Koder.ai (منصة محادثة لتوليد وتكرار تطبيقات الويب، الباكند، والجوال)، فاثنان من الميزات تتماشى مع هذا العقل:
حتى لو لم تكن تولّد كوداً جديداً أثناء حادث، تلك العادات — فروق صغيرة، نتائج قابلة للقياس، وقابلية التراجع السريعة — هي نفس العادات التي يروّج لها Gregg.
الساعة 10:15 صباحاً ولوحة القيادة تُظهر ارتفاع p99 لواجهة API من ~120ms إلى ~900ms أثناء ذروة الحركة. معدل الأخطاء ثابت، لكن العملاء يشتكون من "بطء" الطلبات.
ابدأ من الخدمة: Rate, Errors, Duration.
تقطّع Duration حسب نقطة النهاية وتجد مساراً واحداً يهيمن على p99: POST /checkout. الإنتاجية ازدادت 2×، الأخطاء طبيعية، لكن Duration يقفز تحديداً عند ارتفاع التزامن. هذا يشير إلى الطوابير أو التداخل، وليس فشل واضح.
تحقق إذا ما كان الكمون هو وقت حسابي أم انتظار: قارن "زمن المعالج" بالتطبيق مقابل زمن الطلب الكلي (أو spans الصاعدة-الهابطة إن توافرت). زمن المعالج منخفض، والزمن الكلي مرتفع — الطلبات تنتظر.
جرد الاختناقات المحتملة: الاستفادة، التشبع، الأخطاء للـ CPU، الذاكرة، القرص، والشبكة.
استهلاك CPU ~35% فقط، لكن صف التشغيل (run queue) والتبديلات السياقية ترتفع. ذلك التناقض (CPU منخفض، انتظار مرتفع) إشارة كلاسيكية: الخيوط ليست تحرق CPU — إنها محجوزة.
تلتقط بروفايل خارج-CPU خلال الذروة وتجد وقتاً كثيراً في mutex حول كاش تحقق "الترقيات" المشترك.
تستبدل القفل العام بقفل لكل مفتاح (أو مسار قراءة خالٍ من الأقفال)، تنشر، وتراقب عودة p99 إلى القاعدة بينما يبقى Rate مرتفعاً.
قائمة ما بعد الحادث: