مختبرا الأداء والتصحيح البصري
درس 3 من 8
3مختبرا الأداء والتصحيح البصري
قبل الغوص في تعقيدات C، هذا الجزء يبني عادتين مهنيتين: قياس أداء الكود بدل تخمينه، ومراقبة تنفيذه خطوة بخطوة بدل تخمين مكان الخطأ.
ماذا تشاهد في الرسم: تقيس مرات كثيرة وتأخذ الوسيط، ثم تغيّر شيئًا واحدًا فقط وتقيس من جديد، فتعرف أن الفرق سببه التغيير.
خارطة هذا الجزء
المفاهيم بالترتيب، اضغط أيًّا منها للقفز إليه:
طريقان إلى نفس الفكرة
قبل أن تقول «هذا الكود بطيء» قِسه بساعة، كما يقيس المدرّب زمن العدّاء بدل أن يقول «يبدو سريعًا». وقبل أن تخمّن مكان الخطأ، شاهد البرنامج وهو يعمل خطوة بخطوة، كمن يعيد مشهد المباراة بالتصوير البطيء.
القياس يعني تشغيل نفس العمل عدة مرات بأداة مثل time أو timeit ومقارنة الأرقام، لا الحدس. والتصحيح البصري يعني تتبّع التنفيذ سطرًا سطرًا ورؤية قيم المتغيرات والذاكرة في كل خطوة بأداة مثل Python Tutor أو gdb.
الفكرة الجوهرية
1القياس المعياري (Benchmarking)
قياس زمن تنفيذ الكود واستهلاكه للموارد (المعالج، الذاكرة، الطاقة) بأرقام فعلية، لا انطباعات. "أشعر أن هذا الكود بطيء" ليس بيانًا هندسيًا، "هذا الكود يستغرق 340 مللي ثانية مقابل 12 مللي ثانية لبديله" هو بيان هندسي. وللقياس الموثوق قواعد: تُكرَّر التجربة عدة مرات (لا قياس واحد) وتُؤخذ القيمة الوسطى، لأن ضجيج النظام (عمليات أخرى في الخلفية، تغيّر حرارة المعالج) يجعل كل تشغيل منفرد مختلفًا قليلًا؛ ويُغيَّر متغيّر واحد فقط بين التجربتين (نفس المُدخل، نفس الجهاز) حتى تتأكد أن الفرق في النتيجة سببه التغيير الذي قصدته لا عامل آخر دخل بالصدفة.
2الكفاءة والحوسبة الخضراء
كل عملية حسابية تستهلك طاقة كهربائية فعلية. كود غير كفؤ يعمل على ملايين الأجهزة يعني استهلاكًا إضافيًا حقيقيًا للطاقة على مستوى العالم، الكفاءة ليست ترفًا تقنيًا فقط.
3التصحيح البصري (Visual Debugging)
أدوات مثل Python Tutor تعرض حالة كل متغيّر والذاكرة بصريًا بعد كل سطر يُنفَّذ، هذا يحوّل "التخمين" في التصحيح إلى "مشاهدة مباشرة" لمكان انحراف البرنامج عن توقعك.
كيف تطبّق هذا عمليًا
| السؤال | الأداة/الطريقة |
|---|---|
| كم من الوقت يستغرق تنفيذ هذه الدالة؟ | أدوات قياس الوقت (مثل time في الشل، أو مكتبات القياس المدمجة في اللغة) |
| أين بالضبط تنحرف قيمة متغيّر عن توقعي؟ | تتبّع بصري خطوة بخطوة (Python Tutor) أو نقاط توقّف (Breakpoints) في مصحّح أخطاء |
| هل هذا الحل أكفأ من ذاك؟ | قياس نفس المُدخل على كلا الحلّين وموازنة الأرقام مباشرة، لا التخمين النظري وحده |
تعمّق: منهج القياس والتتبع
تحوّل هذه المختبرات الأداء والتصحيح من إحساس إلى منهج: قِس بدل أن تخمّن، وتتبّع بدل أن تظن. نفصّل منطق القياس، وسبب تذبذب الأرقام، وطريقة تتبّع الأخطاء الشائعة.
أولًا: ماذا يقيس clock() بالضبط؟
تعيد الدالة clock() الزمن الذي استهلكته عمليتك على المعالج، بوحدات داخلية تقسمها على الثابت CLOCKS_PER_SEC لتحصل على ثوانٍ. هذا غير الزمن الجداري (Wall Time) الذي يمرّ على ساعة الحائط، فلو انتظر برنامجك دخلًا من المستخدم فالانتظار لا يُحسب في زمن المعالج لكنه يُحسب في الجداري. أما الأمر time في الشل فيعرض الأنواع الثلاثة: real الجداري، و user زمن شيفرتك، و sys زمن النواة نيابة عنك.
ثانيًا: لماذا تتذبذب الأرقام؟
شغّل البرنامج نفسه عشر مرات تحصل على عشرة أرقام مختلفة. السبب أن الجهاز يعمل عليه غيرك: عمليات أخرى، وذاكرة تخبئة (Cache) باردة في المرة الأولى، وتبدّل سرعة المعالج بحسب الحرارة والطاقة. ولذلك لا تُعتمد قياسة واحدة. ثلاث ممارسات تصنع قياسًا أمينًا: كرّر القياس عدة مرات، واستعمل الوسيط (Median) لأنه لا يتأثر بقيمة شاذة واحدة، وثبّت كل شيء ما عدا ما تقارنه (نفس المدخل، نفس أعلام الترجمة، نفس الجهاز).
شكل 1، منهج المقارنة العادلة بين تنفيذين.
ثالثًا: الكفاءة والطاقة
الطاقة المستهلكة تقريبًا هي القدرة الكهربائية × الزمن، فالبرنامج الأقل عمليات يستهلك أقل طاقة في الغالب. لهذا تهم تعقيدية الخوارزمية (Big O) في الحوسبة الخضراء: مضاعفة المدخل في خوارزمية تربيعية تضرب الزمن أربع مرات. لكن لا تُقاس الكفاءة بالسرعة وحدها: قد يكون الأسرع أكثر استهلاكًا للذاكرة أو الطاقة، ولهذا يربط المختبر القياس بتقرير يشرح السبب لا مجرد الأرقام.
رابعًا: تتبّع الأخطاء المنطقية بصريًا
أداة Python Tutor تنفّذ شيفرتك سطرًا بسطر وتعرض قيم المتغيرات بعد كل خطوة، أي أنها تؤتمت جدول التتبع الذي تعلّمته. الأخطاء التي تكشفها غالبًا من أربع عائلات:
| الخطأ | العَرَض | كيف يظهر في التتبع |
|---|---|---|
| خطأ بفارق واحد (Off-by-one) | حلقة تدور مرة زائدة أو ناقصة | انظر آخر قيمة لعدّاد الحلقة: هل تجاوزت الحد؟ |
| متغير تحكم خاطئ | حلقة لا تنتهي أو تنتهي فورًا | المتغير في الشرط لا يتغير في الجسم |
| تحديث ناقص | نتيجة صحيحة جزئيًا | متغير يُحسب لكن لا يُسند قيمته |
| إساءة استخدام القيمة المُعادة | قيمة غير متوقعة بعد النداء | الدالة أعادت قيمة لم يلتقطها أحد |
شكل 2، التتبع ينهي التخمين: ابحث عن أول لحظة تنحرف فيها الحالة عن المتوقع.
جرّب بنفسك
لماذا يُعدّ «أشعر أن هذا الكود بطيء» بيانًا غير هندسي؟
القياس المعياري (Benchmarking) يستبدل الانطباع بأرقام قابلة للتكرار.
ما الذي يقدّمه التصحيح البصري (Python Tutor) مقارنةً بالتخمين؟
يحوّل التصحيح من تخمين إلى مشاهدة مباشرة لحالة البرنامج سطرًا بسطر.
لماذا تتذبذب أرقام زمن التنفيذ بين تشغيلة وأخرى؟
الحمل على المعالج يتغيّر، لذا تُكرَّر القياسات ويُؤخذ المتوسط أو الأدنى قبل أي استنتاج.
بطاقات مراجعة سريعة
تحقق من فهمك
لو حسّنت دالة تُستدعى مرة واحدة فقط في برنامجك، وتركت دالة أخرى تُستدعى ملايين المرات كما هي، هل هذا قرار جيد؟
على الأرجح لا، الأثر الحقيقي على الأداء الكلي يأتي من الدوال شديدة التكرار، لا النادرة، حتى لو كانت أبطأ نسبيًا في كل استدعاء منفرد. القياس الشامل يكشف أين يستحق التحسين وقتك فعلاً.
قِست برنامجًا مرة واحدة فكان الأول أسرع بنسبة 3%، هل تستنتج؟
لا: الفرق قد يكون ضمن التذبذب؛ كرّر القياس واستعمل الوسيط وزد حجم المدخل.
مصادر هذا الدرس
مرتّبة بالنوع. ابدأ بالتوثيق الرسمي إذا تبي المرجع الدقيق، وبالمقال أو الفيديو إذا تبي الشرح أولًا.
فيديو1
خلّصت الدرس؟
سجّل الدخول ليُحفظ تقدّمك.