إدارة الذاكرة بفعالية في الألعاب

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

توضّح هذه الصفحة الخطوات التي يمكنك اتّخاذها لتجنُّب حالات نقص الذاكرة التي تؤثّر في لعبتك.

الاستجابة للدالة onTrimMemory()

يستخدم النظام onTrimMemory() لإشعار تطبيقك بأحداث مراحل النشاط التي تمثّل فرصة جيدة لتخفيض تطبيقك طوعًا لمقدار الذاكرة التي يستخدمها وتجنُّب إغلاقه من خلال عملية إغلاق التطبيقات بسبب نقص الذاكرة (LMK) بهدف توفير الذاكرة لاستخدامها في تطبيقات أخرى.

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

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

Kotlin

class MainActivity : AppCompatActivity(), ComponentCallbacks2 {
    override fun onTrimMemory(level: Int) {
        if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
            // Release memory related to UI elements, such as bitmap caches.
        }
        if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
            // Release memory related to background processing, such as by
            // closing a database connection.
        }
    }
}

Java

public class MainActivity extends AppCompatActivity implements ComponentCallbacks2 {
    public void onTrimMemory(int level) {
        switch (level) {
            if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
                // Release memory related to UI elements, such as bitmap caches.
            }
            if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
                // Release memory related to background processing, such as by
                // closing a database connection.
            }
        }
    }
}

#C

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

class LowMemoryTrigger : MonoBehaviour
{
    private void Start()
    {
        Application.lowMemory += OnLowMemory;
    }
    private void OnLowMemory()
    {
        // Respond to low memory condition (e.g., Resources.UnloadUnusedAssets())
    }
}

الالتزام بميزانيات الذاكرة

يجب تخصيص الذاكرة بشكل معتدل لتجنُّب نفادها. تشمل بعض النقاط التي يجب أخذها في الاعتبار ما يلي:

  • حجم ذاكرة الوصول العشوائي (RAM) الفعلية: غالبًا ما تستخدم الألعاب ما بين ربع ونصف مقدار ذاكرة الوصول العشوائي (RAM) الفعلية على الجهاز.
  • الحد الأقصى لحجم zRAM: يعني توفّر مساحة أكبر في zRAM أنّ اللعبة يمكنها تخصيص مساحة أكبر من الذاكرة. يمكن أن يختلف هذا المبلغ حسب الجهاز. ابحث عن SwapTotal في /proc/meminfo للعثور على هذه القيمة.
  • استخدام نظام التشغيل للذاكرة: الأجهزة التي تخصص المزيد من ذاكرة الوصول العشوائي لعمليات النظام تترك مساحة أقل من الذاكرة للعبتك. يوقف النظام عملية لعبتك قبل إيقاف عمليات النظام.
  • استخدام الذاكرة في التطبيقات المثبَّتة: اختبِر لعبتك على الأجهزة التي تم تثبيت العديد من التطبيقات عليها. يجب أن تعمل تطبيقات التواصل الاجتماعي والمحادثة باستمرار، ما يؤثر في مقدار الذاكرة المتوفرة.

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

تجنُّب التبديل المفرط

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

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

استخدام الأدوات المتاحة

يتضمّن نظام التشغيل Android مجموعة من الأدوات للمساعدة في فهم كيفية إدارة النظام للذاكرة.

Meminfo

تجمع هذه الأداة إحصاءات الذاكرة لعرض مقدار ذاكرة PSS التي تم تخصيصها والفئات التي تم استخدامها فيها.

اطبع إحصاءات meminfo بإحدى الطرق التالية:

  • استخدِم الأمر adb shell dumpsys meminfo package-name.
  • استخدِم طلب البيانات MemoryInfo من Android Debug API.

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

نقاط تتبُّع الذاكرة

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

‫Perfetto وآثار الأنشطة طويلة المدة

Perfetto هي مجموعة من الأدوات لجمع معلومات الأداء والذاكرة على أحد الأجهزة وعرضها في واجهة مستخدم مستندة إلى الويب. يتيح هذا الخيار تتبُّع عمليات طويلة بشكل عشوائي، ما يتيح لك الاطّلاع على كيفية تغيُّر RSS بمرور الوقت. يمكنك أيضًا إصدار طلبات بحث SQL على البيانات التي ينتجها من أجل المعالجة بلا إنترنت. فعِّل عمليات التتبُّع الطويلة من خلال تطبيق "تتبُّع النظام". تأكَّد من تفعيل الفئة الذاكرة:الذاكرة لعملية التتبُّع.

heapprofd

heapprofd هي أداة لتتبُّع الذاكرة تندرج ضمن Perfetto. يمكن أن تساعدك هذه الأداة في العثور على تسريبات الذاكرة من خلال عرض المكان الذي تم فيه تخصيص الذاكرة باستخدام malloc. يمكن بدء heapprofd باستخدام نص برمجي بلغة Python، وبما أنّ الأداة تتطلّب موارد قليلة، فهي لا تؤثّر في الأداء مثل الأدوات الأخرى، مثل Malloc Debug.

تقرير الأخطاء

bugreport هي أداة لتسجيل البيانات تتيح معرفة ما إذا كانت لعبتك قد تعطلت بسبب نفاد الذاكرة أم لا. تكون نتائج الأداة أكثر تفصيلاً من استخدام logcat. وهي مفيدة لتصحيح أخطاء الذاكرة لأنّها توضّح ما إذا كانت لعبتك قد تعطّلت بسبب نفاد الذاكرة أو بسبب إغلاقها من خلال عملية LMK.

لمزيد من المعلومات، يُرجى الاطّلاع على تسجيل تقارير الأخطاء وقراءتها.