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

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

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

الاستجابة إلى onTrimMemory()

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

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

Kotlin

class MainActivity : AppCompatActivity(), ComponentCallbacks2 {
    override fun onTrimMemory(level: Int) {
        when (level) {
            ComponentCallbacks2.TRIM_MEMORY_MODERATE,
                ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW,
                ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL -> // Respond to low memory condition
            else -> Unit
        }
    }
}

Java

public class MainActivity extends AppCompatActivity implements ComponentCallbacks2 {
    public void onTrimMemory(int level) {
        switch (level) {
            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
              // Respond to low memory condition
                break;
            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
              // Respond to low memory condition
                break;
            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
              // Respond to low memory condition
                break;
            default:
                break;

#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())
    }
}

استخدام الإصدار التجريبي من Memory Advice API

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

لاستخدام واجهة برمجة التطبيقات Memory Advice API، استخدِم دليل البدء.

توخّي الحذر عند استخدام ميزانيات الذاكرة

ذاكرة الميزانية بشكل متحفظ لتجنب نفاد الذاكرة. تتضمن بعض العناصر التي ينبغي مراعاتها ما يلي:

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

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

تجنب الثقب

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

يتمثل أحد أعراض حدوث انهيار الكاميرا في زيادة وقت عرض اللقطات - ربما لثانية واحدة أو أكثر. قم بتقليل مساحة ذاكرة اللعبة لحل هذا الموقف.

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

لدى Android مجموعة من الأدوات للمساعدة في فهم طريقة إدارة النظام للذاكرة.

معلومات Meminfo

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

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

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

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

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

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

Perfetto والآثار الطويلة

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

هابروفد

heapprofd هي أداة لتتبُّع الذاكرة ضمن Perfetto. يمكن لهذه الأداة مساعدتك في العثور على تسرّب الذاكرة من خلال عرض المكان الذي تم تخصيص الذاكرة فيه باستخدام malloc. يمكن بدء heapprofd باستخدام نص برمجي في Python، ونظرًا لاحتواء الأداة على حمل زائد، لا يؤثر ذلك في الأداء مثل أدوات أخرى مثل Maroc Debug.

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

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

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