تحليل كود Java: إيجاد نقاط الاختناق عمليًا

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

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

ابدأ الدورة

مقدمة: لماذا تحليل كود Java؟

\n\n

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

\n\n

التحليل هو عملية جمع بيانات حول أداء التطبيق: وقت تنفيذ الدوال، استخدام الذاكرة، الخيوط، وحمل المعالج. بدونها، يتحول التحسين إلى تخمين. في هذه المقالة، سنستعرض أمثلة عملية لتحليل كود Java، ونتعلم تفسير النتائج وإيجاد نقاط الاختناق.

\n\n

سننظر في أداتين شائعتين: VisualVM (مجاني، مدمج في JDK) و JProfiler (تجاري ولكنه قوي). جميع الأمثلة ستكون بكود حقيقي.

\n\n

الجزء الرئيسي: ممارسة التحليل

\n\n

1. إعداد البيئة وتشغيل المحلل

\n\n

أولاً، تأكد من تثبيت JDK (الإصدار 8 أو أعلى). يأتي VisualVM مع JDK 8 و 9، أما للإصدارات الأحدث فيجب تنزيله بشكل منفصل من الموقع الرسمي.

\n\n

لنكتب كودًا بسيطًا "بطيئًا" للاختبار. أنشئ فئة SlowApp.java:

\n\n
import java.util.ArrayList;\nimport java.util.List;\nimport java.util.Random;\n\npublic class SlowApp {\n    public static void main(String[] args) throws InterruptedException {\n        List<String> data = new ArrayList<>();\n        Random random = new Random();\n\n        // محاكاة تحميل بيانات طويل\n        for (int i = 0; i < 100_000; i++) {\n            data.add(generateString(random));\n        }\n\n        // معالجة البيانات\n        long sum = 0;\n        for (String s : data) {\n            sum += processString(s);\n        }\n\n        System.out.println("Result: " + sum);\n        Thread.sleep(10000); // لإتاحة الوقت للاتصال بالمحلل\n    }\n\n    private static String generateString(Random random) {\n        StringBuilder sb = new StringBuilder(100);\n        for (int i = 0; i < 100; i++) {\n            sb.append((char) ('a' + random.nextInt(26)));\n        }\n        return sb.toString();\n    }\n\n    private static long processString(String s) {\n        long result = 0;\n        for (char c : s.toCharArray()) {\n            result += c;\n            // تأخير اصطناعي\n            for (int j = 0; j < 100; j++) {\n                result += Math.sqrt(j);\n            }\n        }\n        return result;\n    }\n}
\n\n

قم بتشغيل التطبيق:

\n
javac SlowApp.java\njava SlowApp
\n\n

أثناء تشغيل البرنامج (سينام لمدة 10 ثوانٍ)، افتح VisualVM. في اللوحة اليسرى، ابحث عن عمليتك (SlowApp) وانقر نقرًا مزدوجًا. انتقل إلى علامة التبويب Sampler أو Profiler - سترى إحصائيات المعالج والذاكرة.

\n\n

2. تحليل المعالج: إيجاد الدالة الأكثر استهلاكًا

\n\n

في VisualVM، اضغط على زر CPU في قسم Sampler. بعد بضع ثوانٍ، ستحصل على جدول بالدوال مرتبة حسب وقت التنفيذ (Self Time).

\n\n

في مثالنا، سترى أن الدالة processString تستهلك أكثر من 80% من الوقت. داخلها، الحلقة المتداخلة Math.sqrt(j). هذه هي نقطة الاختناق.

\n\n

كيف نفسر ذلك؟

\n
    \n
  • Self Time - الوقت المستغرق مباشرة في تنفيذ الدالة (بدون احتساب استدعاءات الدوال الفرعية).
  • \n
  • Total Time - الوقت الإجمالي بما في ذلك جميع الاستدعاءات المتداخلة.
  • \n
  • Invocations - عدد مرات استدعاء الدالة.
  • \n
\n\n

مثال على المخرجات (مبسط):

\n
Method                          Self Time (ms)   Invocations\nSlowApp.processString           8500              100000\nSlowApp.generateString          1200              100000\njava.lang.Math.sqrt             6000                

المدونات

توصيات الكتب