تحليل أداء كود JavaScript: إيجاد نقاط الاختناق للمبتدئين

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

تحليل أداء كود JavaScript: إيجاد نقاط الاختناق

\n\n

عندما يبدأ مشروع Node.js الخاص بك في التباطؤ، أول فكرة تتبادر إلى الذهن هي "يجب إعادة كتابة كل شيء بلغة Rust". لكن لا تتعجل! غالباً ما تكمن المشكلة في بضعة أسطر من الكود تعمل بشكل غير فعال. في هذه المقالة، سنشرح كيفية إيجاد هذه "الاختناقات" باستخدام أدوات تحليل أداء بسيطة. ستتعلم كيفية قياس الأداء، وإنشاء flamegraph، وفهم أين تذهب طاقة المعالج (CPU).

\n\n

لماذا تحليل أداء الكود؟

\n\n

تخيل أن خادمك يعالج 100 طلب في الثانية، بينما تحتاج إلى 500. يمكنك تحسين كل شيء عشوائياً، لكن هذا سيستغرق أسابيع. أو يمكنك إيجاد دالة واحدة تستغرق 80% من الوقت، وإصلاحها في ساعة. تحليل الأداء هو بالضبط ما يوضح أين يضيع الوقت.

\n\n

لننظر في السيناريوهات الرئيسية التي يكون فيها تحليل الأداء ضرورياً:

\n
    \n
  • زمن استجابة عالي لواجهات API
  • \n
  • تسرب الذاكرة (memory leaks)
  • \n
  • حمل عالي على المعالج (CPU) دون أسباب واضحة
  • \n
  • معالجة بطيئة لمصفوفات بيانات كبيرة
  • \n
\n\n

الأداة 1: محلل Node.js المدمج (--prof)

\n\n

أبسط طريقة هي تشغيل Node.js مع العلم --prof. يقوم بجمع إحصائيات التنفيذ وحفظها في ملف isolate-*.log.

\n\n

لننشئ سكريبت اختبار يحتوي على نقطة اختناق:

\n\n
// slow.js\nfunction heavyComputation() {\n    let sum = 0;\n    for (let i = 0; i < 1e7; i++) {\n        sum += Math.sqrt(i) * Math.sin(i);\n    }\n    return sum;\n}\n\nfunction fastFunction() {\n    return 42;\n}\n\nconsole.time('total');\nheavyComputation();\nfastFunction();\nconsole.timeEnd('total');\n
\n\n

لنشغل تحليل الأداء:

\n
node --prof slow.js
\n\n

بعد التنفيذ، سيظهر ملف isolate-0x...-v8.log. لقراءته، نستخدم الأداة node --prof-process:

\n
node --prof-process isolate-0x...-v8.log > profile.txt
\n\n

لنفتح profile.txt وسنرى جدولاً بنسب الوقت:

\n
[Summary]:\n   ticks  total  nonlib   name\n   785    78.5%  85.3%   JavaScript\n   215    21.5%  14.7%   C++\n   ...\n[Bottom up (heavy) profile]:\n  ticks parent  name\n   500   50.0%   LazyCompile: *heavyComputation slow.js:2:17\n   100   10.0%   Builtin: MathSqrt\n    50    5.0%   Builtin: MathSin\n
\n\n

نرى أن 50% من الوقت يذهب إلى الدالة heavyComputation. الآن نعرف ما يجب تحسينه أولاً.

\n\n

الأداة 2: Chrome DevTools (المفتش)

\n\n

لتحليل أكثر وضوحاً، سنتصل بـ Chrome DevTools. لنشغل Node.js مع العلم --inspect:

\n
node --inspect slow.js
\n\n

لنفتح Chrome ونذهب إلى العنوان chrome://inspect. نضغط على "Open dedicated DevTools for Node". علامة التبويب "Profiler" ← "Start" ← شغّل السكريبت ← "Stop".

\n\n

سترى flamegraph - رسم بياني حيث عرض الكتلة يظهر وقت التنفيذ. كلما كانت الكتلة أعرض، كانت الدالة "أسخن". ستكون heavyComputation لدينا مستطيلاً ضخماً.

\n\n

نصيحة: استخدم فلتر "Focus selected" على الدالة لرؤية استدعاءاتها الداخلية. على سبيل المثال، ستلاحظ أن Math.sqrt يتم استدعاؤه 10 ملايين مرة - ربما يجب حساب الجذور مسبقاً.

\n\n

الأداة 3: perf_hooks - قياسات دقيقة داخل الكود

\n\n

أحياناً تحتاج لقياس جزء معين من الكود دون تشغيل أدوات خارجية. لهذا نستخدم الوحدة المدمجة perf_hooks.

\n\n

مثال لقياس وقت تنفيذ دالة:

\n\n
const { performance } = require('perf_hooks');\n\nfunction processData(items) {\n    let result = [];\n    for (let item of items) {\n        // محاكاة معالجة معقدة\n        for (let j = 0; j < 1000; j++) {\n            result.push(item * j);\n        }\n                

المدونات

توصيات الكتب