متطلبات الذاكرة الضخمة في Android - ماذا تفعل؟

مرحبا ايها القراء.

نلفت انتباهكم اليوم إلى القليل من المواد حول الاستخدام المختص للذاكرة في Android .



استمتع بالقراءة!

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

أولاً ، نظرية صغيرة


تعمل معظم تطبيقات Android في أعلى وقت التشغيل ( ART ) ، الذي حل محل آلة Dalvik الافتراضية التي عفا عليها الزمن الآن. تتشابه ART و Dalvik مع Java Virtual Machine (JVM) ، حيث يتشاركان مبادئ تصميم مماثلة. يستخدمون مسافتين منفصلتين لتخزين بيانات التطبيق: المكدس والكومة.

ذاكرة

المكدس تستخدم ذاكرة المكدس في جافا لتخزين المتغيرات المحلية (الأنواع البدائية ومراجع الكائنات). يحتوي كل مؤشر ترابط Java على مكدس منفصل خاص به. ذاكرة المكدس صغيرة نسبيًا مقارنة بذاكرة كومة الذاكرة المؤقتة. حجم مكدس Java الخاص بـ Dalvik هو عادةً 32 كيلوبايت لرمز Java و 1 ميجابايت للرمز الأصلي (C ++ / JNI). ظهرت حزمة موحدة لـ Java و C ++ في ART ، يبلغ حجمها حوالي 1 ميغابايت.

عندما يحدد التطبيق ذاكرة المكدس بالكامل إلى الحد الأقصى ، يتم طرح خطأ StackOverflowError. الأسباب الأكثر احتمالاً للوصول إلى حد المكدس هي إما العودية اللانهائية أو استدعاء أسلوب عميق للغاية. يتم دائمًا الإشارة إلى ذاكرة المكدس بترتيب LIFO (آخر يأتي - يتم تقديمه أولاً). في كل مرة يتم استدعاء طريقة ، يتم دفع إطار جديد إلى المكدس مع المتغيرات المحلية لهذه الطريقة. عند اكتمال الطريقة ، يتم إخراج إطارها من المكدس ، ويتم إرسال أي قيمة ناتجة محتملة إلى المكدس. لذا ، فإن المشكلة الأولى (العودية اللانهائية) هي خطأ يسهل إصلاحه ، لكن الثانية تتطلب بعض إعادة البناء ، والتي تتمثل في نشر استدعاءات الطريقة العودية وتحويلها إلى حلقة.

كومة الذاكرة

يستخدم جهاز ظاهري كومة الذاكرة في Java لتخصيص الكائنات. عندما يتم إنشاء كائن ، يحدث في كومة الذاكرة المؤقتة. تقوم الأجهزة الافتراضية ، مثل JVM أو ART ، بجمع النفايات بشكل منتظم ، وإزالة جميع الكائنات التي لم تعد مرجعية ، وبالتالي تحرير الذاكرة لتخصيص كائنات جديدة.
لضمان سهولة الاستخدام ، يحد نظام Android من أحجام الكومة بدقة لكل تطبيق قيد التشغيل. يختلف حد حجم كومة الذاكرة المؤقتة من جهاز لآخر ويعتمد على مقدار ذاكرة الوصول العشوائي الموجودة على هذا الجهاز. إذا وصل التطبيق الخاص بك إلى الحد الأقصى لحجم كومة الذاكرة المؤقتة وحاول تخصيص المزيد من الذاكرة ، يتم إنشاء خطأ OutOfMemoryErrorوينتهي التطبيق. دعونا نلقي نظرة على بعض الأمثلة للمساعدة في تجنب هذا الموقف.

تحليل ذاكرة الكومة


أهم أداة لفهم مشاكل الذاكرة في تطبيقاتك وفهم كيفية استخدام الذاكرة هي أداة تعريف الذاكرة المتوفرة في Android Studio.

تصور هذه الأداة مقدار الذاكرة التي يستهلكها تطبيقك بمرور الوقت. يمكنك أخذ لقطات من كومة Java في تطبيق قيد التشغيل ، وتسجيل عمليات تخصيص الذاكرة ، وتتبع الكومة أو محفوظات تخصيص الذاكرة في واجهة مستخدم قوية.

يجب أن تبدو جلسة ملف تعريف الذاكرة النموذجية كما يلي:

  • نحن ننظر إلى عمليات تخصيص الذاكرة الأكثر تكرارًا وممرات جامعي القمامة لتحديد مشاكل الأداء المحتملة.
  • , , , , , . , . , , PdfActivity PSPDFKit .
  • , . , . – , , .


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

مكتبة LeakCanary هي حل مثالي للكشف عن تسرب الذاكرة . يصدر تلقائيًا إشعارات عندما تكون في مجموعة الاختبار (بناء التطوير) ، مما يمنحك معدل تتبع التسرب في واجهة المستخدم لهذا البرنامج. يمكنك (ويجب) دمجها اليوم ، خاصة أنها ليست صعبة!

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

تحرير الذاكرة ردا على الأحداث


قد يتطلب Android من التطبيق تخصيص ذاكرة ، أو ببساطة إجباره على الإنهاء عندما تحتاج إلى تحرير الذاكرة لأداء مهام أكثر أهمية. قبل حدوث ذلك ، سيسمح لك النظام بإعطاء كل الذاكرة التي لا تحتاجها. في نشاطك ، ستحتاج إلى تنفيذ واجهة ComponentCallbacks2. في هذه الحالة ، كلما نفدت ذاكرة النظام الخاص بك ، سيتم إجراء مكالمة على طريقتك onTrimMemory()، وستتمكن من تحرير الذاكرة أو تعطيل الميزات التي لن تعمل في ظل ظروف نقص الذاكرة هذه.

لذلك ، يتم التعامل مع عمليات رد الاتصال هذه في تطبيق PSPDFKit. تم تصميم تطبيق PSPDFKit مع حساب الاستخدام النشط للذاكرة للتخزين المؤقت ، بحيث يعمل التطبيق بسلاسة قدر الإمكان. في البداية ، من غير المعروف مقدار الذاكرة المتوفرة على الجهاز ، لذلك يتكيف PSPDFKit مع الموقف ويحد من استخدام الذاكرة عندما يتلقى إشعارات بعدم وجود ذاكرة كافية. لذلك ، تعمل التطبيقات المدمجة مع PSPDFKit حتى على الأجهزة ذات التقنية المنخفضة ، ولكن مع انخفاض الأداء بسبب تعطيل التخزين المؤقت.

كومة كبيرة


أحد الحلول الأمامية للتعامل مع متطلبات الذاكرة العالية هو طلب مجموعة كبيرة من Dalvik لتطبيقك. للقيام بذلك ، يمكنك الإضافة android:largeHeap="true"إلى علامة <application> في الملف AndroidManifest.xml.

إذا largeHeapتم تعيين الخاصية على القيمة true، فسيقوم Android بإنشاء جميع العمليات لتطبيقك بكومة كبيرة. هذا الإعداد مخصص فقط للتطبيقات التي ، بحكم طبيعتها ، لا يمكنها العمل بدونها ، أي أنها تستخدم موارد ضخمة يجب أن تتناسب مع الذاكرة في نفس الوقت.

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

تحقق من مقدار الذاكرة التي يمكن لتطبيقك استخدامها


لن يضر أبدًا بالتحقق من حجم كومة تطبيقك والتكيف الديناميكي للشفرة والإمكانيات المتاحة ديناميكيًا مع حدود الذاكرة هذه. يمكنك التحقق من الحد الأقصى لحجم كومة الذاكرة المؤقتة مباشرة في وقت التشغيل باستخدام طرق getMemoryClass()أو getLargeMemoryClass()(عند تمكين كومة كبيرة).

يدعم Android حتى الأجهزة التي تحتوي على 512 ميغابايت فقط من ذاكرة الوصول العشوائي. تأكد من عدم تجاهل الأجهزة ذات التقنية المنخفضة! باستخدام الطريقةisLowRamDevice()يمكنك التحقق مما إذا كان تطبيقك يعمل على مثل هذا الجهاز حيث لا تتوفر ذاكرة كافية. يعتمد السلوك الدقيق لهذه الطريقة على الجهاز ، ولكنه عادةً ما يرجع بشكل صحيح على الأجهزة التي تحتوي على أقل من 1 غيغابايت من ذاكرة الوصول العشوائي. تحتاج إلى التأكد من أن تطبيقك يعمل بشكل صحيح على هذه الأجهزة ، وتعطيل جميع الميزات التي تستخدم مساحة كبيرة من الذاكرة عليها.

اقرأ المزيد حول كيفية عمل Android على الأجهزة التي تحتوي على مساحة صغيرة من الذاكرة ، يمكنك القراءة هنا ؛ تتوفر أيضًا نصائح تحسين إضافية هنا.

استخدم بنيات البيانات المحسنة


في كثير من الحالات ، تستخدم التطبيقات مساحة كبيرة من الذاكرة لسبب بسيط هو أنها لا تستخدم هياكل البيانات الأكثر ملاءمة.

لا يمكن لمجموعات Java تخزين الأنواع البدائية الفعالة وتتطلب تعبئة مفاتيحها وقيمها. على سبيل المثال ، HashMapمع المفاتيح الصحيحة يجب استبدالها بأخرى محسنة SparseArray. في النهاية ، يمكنك دائمًا استخدام المصفوفات الأولية بدلاً من المجموعات ، وهذه فكرة رائعة إذا لم تكن مجموعتك قابلة لتغيير الحجم.

تتضمن هياكل البيانات الأخرى غير الفعالة من حيث استخدام الذاكرة تسلسلات مختلفة. نعم ، بالفعل ، تنسيقات XML أو JSON ملائمة للاستخدام ، يمكنك تقليل استخدام الذاكرة إذا كنت تعمل بتنسيق ثنائي أكثر كفاءة ، على سبيل المثال ، مخازن البروتوكول.

كل هذه الأمثلة ، مع هياكل البيانات الأمثل لتوفير الذاكرة ، ليست سوى تلميحات. كما هو الحال مع إعادة الهيكلة ، يجب عليك أولاً العثور على مصدر المشاكل ، ثم الانتقال إلى تحسينات الأداء هذه.

منع خلط الذاكرة


تقوم أجهزة Java / Android الظاهرية بتخصيص الكائنات بسرعة كبيرة. جمع القمامة سريع جدًا أيضًا. ومع ذلك ، عند تخصيص عدد كبير من الكائنات في فترة زمنية قصيرة ، قد تواجه مشكلة تسمى "اضطراب الذاكرة". في هذه الحالة ، لن يكون لدى الآلة الافتراضية الوقت الكافي لتخصيص الأشياء بهذه السرعة ، وسيتخلص منها جامع القمامة ، وسيبدأ التطبيق في التباطؤ ، وفي الحالات القصوى سيستخدم حتى كل الذاكرة.

المشكلة الرئيسية في إقليم Android في هذه الحالة هي أننا لا نتحكم في وقت حدوث جمع القمامة. من المحتمل أن يؤدي هذا إلى مشاكل: على سبيل المثال ، يعمل جامع القمامة بالضبط في الوقت الذي تتكشف فيه الرسوم المتحركة على الشاشة ونتجاوز عتبة 16 مللي ثانية ، مما يضمن عرضًا سلسًا للإطارات. لذلك ، من المهم منع التخصيص الزائد للذاكرة في التعليمات البرمجية.

مثال على موقف يؤدي إلى خلط الذاكرة هو تخصيص كائنات كبيرة ، على سبيل المثال ، الطلاء داخل طريقة onDraw()العرض. في هذه الحالة ، يتم إنشاء العديد من الكائنات بسرعة ، ويمكن أن تبدأ مجموعة البيانات المهملة ، مما قد يؤثر سلبًا على أداء هذا العرض. كما ذكر أعلاه ، يجب عليك دائمًا مراقبة استخدام الذاكرة لتجنب مثل هذه المواقف.

استنتاج


يمكن أن تكون ذاكرة الوصول العشوائي (RAM) على الأجهزة المحمولة موردًا محدودًا جدًا. يعد ضمان الاستخدام الفعال للذاكرة في التطبيق أمرًا مهمًا بشكل خاص إذا كان التطبيق الخاص بك يعمل مع كائنات كبيرة نسبيًا ، على سبيل المثال ، الرسومات النقطية (عارضات PDF ، متصفحات الويب ، محررات الصور) أو ملفات الوسائط الكبيرة (محررات الصوت أو الفيديو). باتباع هذه النصائح ، ستتعلم كيفية إنشاء تطبيقات عالية الجودة تعمل بمستوى مقبول ، حتى على أقوى الأجهزة.

All Articles