يمكنك التقاط لقطة لأجزاء من الذاكرة للاطّلاع على العناصر التي تستهلك الذاكرة في تطبيقك في وقت الالتقاط وتحديد عمليات تسرُّب الذاكرة أو سلوك تخصيص الذاكرة الذي يؤدي إلى حدوث تقطُّع وتجمُّد وحتى أعطال في التطبيق. ويكون ذلك مفيدًا بشكل خاص عند أخذ عمليات تفريغ الذاكرة المؤقتة بعد جلسة مستخدم ممتدة، إذ يمكن أن تعرض كائنات لا تزال في الذاكرة، مع أنّها لم تعُد مطلوبة.
توضّح هذه الصفحة الأدوات التي يوفّرها "استوديو Android" لجمع وتحليل عمليات تفريغ الذاكرة المؤقتة. بدلاً من ذلك، يمكنك فحص ذاكرة تطبيقك من سطر الأوامر باستخدام dumpsys، كما يمكنك الاطّلاع على أحداث جمع البيانات المُهمَلة (GC) في أداة Logcat.
أسباب تحليل استخدام تطبيقك للذاكرة
يوفر نظام التشغيل Android بيئة ذاكرة مُدارة، فعندما يحدّد أنّ تطبيقك لم يعُد يستخدم بعض العناصر، يحرّر جامع البيانات غير المرغوب فيها الذاكرة غير المستخدَمة ويعيدها إلى الكومة. يتم باستمرار تحسين الطريقة التي يعثر بها نظام التشغيل Android على الذاكرة غير المستخدَمة، ولكن في مرحلة ما على جميع إصدارات Android، يجب أن يوقف النظام رمزك مؤقتًا. وفي معظم الأحيان، تكون فترات التوقّف غير ملحوظة. ومع ذلك، إذا كان تطبيقك يخصّص الذاكرة بشكل أسرع من قدرة النظام على جمعها، قد يحدث تأخير في تطبيقك إلى أن يحرّر جامع البيانات مقدارًا كافيًا من الذاكرة لتلبية عمليات التخصيص. وقد يؤدي التأخير إلى تخطّي تطبيقك بعض اللقطات، ما يتسبّب في بطء ملحوظ.
حتى إذا لم يكن تطبيقك بطيئًا، يمكن أن يحتفظ بالذاكرة إذا تسرّبت، حتى عندما يكون يعمل في الخلفية. يمكن أن يؤدي هذا السلوك إلى إبطاء أداء الذاكرة في بقية النظام من خلال فرض أحداث غير ضرورية لجمع البيانات المُهمَلة. وفي النهاية، يضطر النظام إلى إيقاف عملية تطبيقك لاستعادة الذاكرة. بعد ذلك، عندما يعود المستخدم إلى تطبيقك، يجب إعادة تشغيل عملية التطبيق بالكامل.
للحصول على معلومات حول ممارسات البرمجة التي يمكن أن تقلّل من استخدام تطبيقك للذاكرة، اطّلِع على إدارة ذاكرة تطبيقك.
نظرة عامة على لقطة لأجزاء من الذاكرة
لالتقاط لقطة لأجزاء من الذاكرة، اختَر مهمة تحليل استخدام الذاكرة (لقطة لأجزاء من الذاكرة) (استخدِم محلّل الأداء: تشغيل "التطبيق" كقابل للتصحيح (بيانات كاملة)) لالتقاط لقطة لأجزاء من الذاكرة. أثناء تفريغ الذاكرة المخصّصة، قد يزداد حجم ذاكرة Java مؤقتًا. وهذا أمر طبيعي لأنّ لقطة لأجزاء من الذاكرة تحدث في العملية نفسها التي يعمل بها تطبيقك وتتطلّب بعض الذاكرة لجمع البيانات. بعد التقاط لقطة لأجزاء من الذاكرة، سيظهر لك ما يلي:
تعرض قائمة الصفوف المعلومات التالية:
- عمليات التخصيص: عدد عمليات التخصيص في الكومة.
حجم الذاكرة الأصلية: إجمالي حجم الذاكرة الأصلية المستخدَمة من خلال نوع العنصر هذا (بالبايت). ستظهر لك الذاكرة هنا لبعض العناصر التي تم تخصيصها في Java لأنّ نظام التشغيل Android يستخدم الذاكرة الأصلية لبعض فئات إطار العمل، مثل
Bitmap.الحجم السطحي: إجمالي مقدار ذاكرة Java التي يستخدمها نوع العنصر هذا (بالبايت).
الحجم المحفوظ: إجمالي حجم الذاكرة المحفوظة بسبب جميع مثيلات هذه الفئة (بالبايت).
استخدِم قائمة "الذاكرة المؤقتة" لفلترة ذاكرات مؤقتة معيّنة:
- ذاكرة التجميع المؤقت للتطبيق (الإعداد التلقائي): هي ذاكرة التجميع المؤقت الأساسية التي يخصّص تطبيقك الذاكرة عليها.
- مجموعة الصور: صورة تشغيل النظام، تحتوي على فئات يتم تحميلها مسبقًا أثناء وقت التشغيل. لا يتم نقل عمليات التخصيص هنا أو إزالتها.
- ذاكرة Zygote المؤقتة: هي ذاكرة مؤقتة بنسخ عند الكتابة يتم فيها إنشاء نسخة من عملية التطبيق في نظام Android.
استخدِم القائمة المنسدلة الخاصة بالترتيب لاختيار طريقة ترتيب عمليات التخصيص:
- الترتيب حسب الصف (الإعداد التلقائي): يتم تجميع جميع عمليات التخصيص استنادًا إلى اسم الصف.
- الترتيب حسب الحزمة: يجمع كل عمليات التخصيص استنادًا إلى اسم الحزمة.
استخدِم القائمة المنسدلة الخاصة بالصفوف لفلترة مجموعات الصفوف:
- جميع الفئات (الإعداد التلقائي): يعرض جميع الفئات، بما في ذلك تلك من المكتبات والوحدات التابعة.
- عرض عمليات تسريب الأنشطة/اللقطات: يعرض الفئات التي تتسبّب في تسريب الذاكرة.
- عرض فئات المشاريع: يعرض هذا الخيار الفئات التي يحدّدها مشروعك فقط.
انقر على اسم صف لفتح جزء النسخة. يتضمّن كل مثيل مُدرَج ما يلي:
- العمق: هو أقصر عدد من القفزات من أي جذر لعملية جمع البيانات غير الضرورية إلى العنصر المحدّد.
- الحجم الأصلي: حجم هذا المثال في الذاكرة الأصلية لا يظهر هذا العمود إلا في الإصدار 7.0 من نظام التشغيل Android والإصدارات الأحدث.
- الحجم المُصغَّر: حجم هذا العنصر في ذاكرة Java.
- الحجم المحفوظ: حجم الذاكرة الذي يهيمن عليه هذا العنصر (وفقًا لشجرة المهيمن).
انقر على مثيل لعرض تفاصيل المثيل، بما في ذلك الحقول والمراجع. أنواع الحقول والمراجع الشائعة هي الأنواع المنظَّمة
،
والمصفوفات
،
وأنواع البيانات الأساسية
في Java. انقر بزر الماوس الأيمن على حقل أو مرجع للانتقال إلى المثيل أو السطر المرتبط به في رمز المصدر.
- الحقول: تعرض جميع الحقول في هذا المثال.
- المراجع: تعرض كل مرجع إلى العنصر المميّز في علامة التبويب النسخة.
رصد الصور النقطية المكرّرة
يمكنك أيضًا رصد الصور النقطية المكرّرة في عرض Heap Dump بدءًا من الإصدار 4 من Android Studio Narwhal.
إليك كيفية العثور عليها:
- فتح علامة التبويب "أداة تحليل الأداء" في "استوديو Android"
- انقر على تفريغ الذاكرة المؤقتة (أو تحليل استخدام الذاكرة)، ثم انقر على "تسجيل" لأخذ لقطة لحالة الذاكرة الحالية في تطبيقك.
- ابحث في نتائج التحليل عن مثلث التحذير الأصفر ⚠️، الذي يستخدمه استوديو Android للإشارة إلى الصور النقطية المكرّرة التي يتم تخزينها عدة مرات.
- بدلاً من ذلك، انتقِل إلى عنوان أداة تحليل الأداء، واختَر فلترة حسب: ثم اختَر الإعداد الصور النقطية المكرّرة.
- انقر على أي إدخال تم الإبلاغ عنه لفتح لوحة معاينة الصورة النقطية، ما يتيح لك معرفة الصورة التي تم تكرارها بالضبط.
- استخدِم هذا التأكيد المرئي لتتبُّع منطق التحميل المكرّر في الرمز البرمجي وتنفيذ استراتيجية تخزين مؤقت أفضل.
العثور على تسرّبات الذاكرة
للفلترة بسرعة حسب الفئات التي قد تكون مرتبطة بتسرُّب الذاكرة، افتح القائمة المنسدلة الخاصة بالفئة وانقر على عرض عمليات تسرُّب الأنشطة/اللقطات. يعرض استوديو Android الفئات التي يعتقد أنّها تشير إلى تسرُّب الذاكرة في مثيلات Activity وFragment في تطبيقك.
للبحث عن تسرُّبات الذاكرة يدويًا، تصفَّح قوائم الفئات والعناصر للعثور على عناصر ذات حجم محتفظ به كبير. ابحث عن حالات تسرُّب الذاكرة الناتجة عن أي مما يلي:
- مراجع طويلة الأمد إلى
ActivityأوContextيمكن أن تؤدي إلى تسرُّب الرسم البياني لتركيب Compose المستضاف (مثلComposeViewوعناصر Compose الفرعية). - تسريب عناصر الحالة في Jetpack Compose (
MutableState) أو عناصر حاملة للحالة أو تعبيرات lambda التي تتضمّنContext - عدم إزالة المستمعين أو المراقبين في حزمة
onDisposeمنDisposableEffect - فئات داخلية غير ثابتة، مثل
Runnable، يمكنها الاحتفاظ بنسخة منActivity. - ذاكرات التخزين المؤقت التي تحتفظ بالكائنات لفترة أطول من اللازم
عند العثور على تسرُّبات محتملة للذاكرة، استخدِم علامتَي التبويب الحقول والمراجع في تفاصيل العنصر للانتقال إلى العنصر أو سطر الرمز المصدري الذي يهمّك.
تفعيل تسرّبات الذاكرة للاختبار
لتحليل استخدام الذاكرة، عليك إجهاد رمز تطبيقك ومحاولة فرض تسريب الذاكرة. إحدى طرق إحداث تسرُّبات الذاكرة في تطبيقك هي تركه يعمل لبعض الوقت قبل فحص الذاكرة المؤقتة. قد تتسرّب التسريبات إلى أعلى عمليات التخصيص في الذاكرة المؤقتة. ومع ذلك، كلما كان التسريب أصغر، زادت المدة التي تحتاجها لتشغيل التطبيق من أجل رصده.
يمكنك أيضًا بدء تسريب الذاكرة بإحدى الطرق التالية:
- دوِّر الجهاز من الوضع العمودي إلى الوضع الأفقي والعكس عدة مرات
أثناء التنقّل بين حالات النشاط المختلفة. يمكن أن يؤدي تدوير الجهاز غالبًا إلى تسرُّب تطبيق
Activity(وبالتالي شجرة واجهة المستخدم المستندة إلى Compose المستضافة وأشجار الحالة المرتبطة بها) إذا كان تطبيقك يتضمّن مرجعًا إلىActivityأوContextداخل العمليات غير المتزامنة أو عناصر الاحتفاظ بالحالة. - التبديل بين تطبيقك وتطبيق آخر أثناء التنقّل بين حالات النشاط المختلفة على سبيل المثال، انتقِل إلى الشاشة الرئيسية، ثم ارجع إلى تطبيقك.
تصدير لقطة لأجزاء من الذاكرة واستيرادها
يمكنك تصدير واستيراد ملف لقطة لأجزاء من الذاكرة من علامة التبويب التسجيلات السابقة في أداة تحليل الذاكرة. يحفظ "استوديو Android" التسجيل كملف .hprof.
بدلاً من ذلك، لاستخدام أداة تحليل ملفات .hprof مختلفة، مثل jhat، عليك تحويل ملف .hprof من تنسيق Android إلى تنسيق ملف Java SE .hprof. لتحويل تنسيق الملف، استخدِم الأداة hprof-conv المتوفّرة في الدليل {android_sdk}/platform-tools/. نفِّذ الأمر hprof-conv
مع وسيطتَين: اسم الملف الأصلي .hprof والموقع الجغرافي الذي سيتم فيه
كتابة ملف .hprof المحوَّل، بما في ذلك اسم ملف .hprof الجديد. على سبيل المثال:
hprof-conv heap-original.hprof heap-converted.hprof