يُعدّ تحسين الذاكرة أمرًا بالغ الأهمية لتقديم تجارب ألعاب مستقرة وعالية الأداء على Android. يقدّم هذا الدليل نظرة عامة على أهمية كفاءة استخدام الذاكرة، وكيفية إدارة نظام التشغيل Android لحدود الذاكرة المخصصة للعمليات، ومقاييس الذاكرة الجديدة في Google Play Console لمساعدتك في مراقبة الجودة الفنية للعبتك وتحسينها.
أهمية تحسين الذاكرة
يُعدّ تحسين ذاكرة لعبتك أمرًا ضروريًا للحفاظ على معدّل الاحتفاظ باللاعبين وتوسيع نطاق التوافق مع الأجهزة والالتزام بمعايير جودة المنصة:
- منع التشغيل على البارد (تجربة المستخدم والاحتفاظ به): عندما ينتقل اللاعب مؤقتًا بعيدًا عن لعبتك (على سبيل المثال، للرد على إشعار أو التحقّق من رسالة)، يضع نظام التشغيل عملية اللعبة في الخلفية. إذا كان استهلاك الذاكرة في الخلفية للعبة مرتفعًا جدًا، فإنّ نظام "إغلاق التطبيقات بسبب نقص الذاكرة" (LMK) يمنح الأولوية لإنهاء عملية اللعبة لاستعادة ذاكرة الوصول العشوائي (RAM) للمهام التي تعمل في المقدّمة. في المرة التالية التي يستأنف فيها المستخدم اللعب، بدلاً من الاستئناف السلس والفوري، يجب أن تخضع اللعبة لبدء تشغيل بارد طويل، أي إعادة تحميل أصول الرسومات الثقيلة والصوت وملفات ثنائية لمحرّك اللعبة بالكامل من مساحة التخزين. ويؤدي الحفاظ على انخفاض استخدام الذاكرة في الخلفية إلى منع عمليات الإيقاف الصامتة في الخلفية، ما يحافظ على حالة المستخدم ويضمن إمكانية استئناف اللاعبين لجلساتهم على الفور. لمزيد من التفاصيل حول سلوك نظام LMK، يُرجى الاطّلاع على دليل مؤشرات Android الحيوية - برامج إنهاء العمليات عند انخفاض الذاكرة.
- استقرار المنظومة المتكاملة والأجهزة: يؤدي الاستخدام غير الفعّال للذاكرة وتسرُّب الذاكرة إلى تدهور حالة النظام بشكل عام. عندما تكون ذاكرة النظام منخفضة، يتعرّض النظام لضغط شديد، ما يؤدي إلى انخفاض عدد اللقطات في الثانية، وتقطُّع واجهة المستخدم، ومشاكل في الصوت. إذا كان ضغط الذاكرة شديدًا جدًا، فإنّ نظام "إغلاق التطبيقات بسبب نقص الذاكرة" (LMK) ينهي العمليات في الخلفية بشكل صارم، ما يجبر التطبيقات الأخرى على مواجهة بطء في التشغيل البارد وفقدان حالة المستخدم عندما ينتقل اللاعبون بين المهام.
- عمليات الإنهاء على مستوى النظام الأساسي: بدءًا من الإصدار 17 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 37)، يصبح النظام أكثر استباقية في إنهاء العمليات التي تستهلك قدرًا كبيرًا من الذاكرة. إذا كانت مساحة تخزين لعبتك كبيرة جدًا، يمكن لنظام التشغيل إنهاء عمليتها فجأة بدون إنشاء تتبع تسلسل استدعاء الدوال البرمجية العادي.
- توافق الأجهزة: على الرغم من أنّ الأجهزة الرائدة تتميز بذاكرة وصول عشوائي (RAM) تتراوح سعتها بين 12 غيغابايت و16 غيغابايت، فإنّ جزءًا كبيرًا من جمهور الألعاب العالمي يستخدم أجهزة مزوّدة بذاكرة وصول عشوائي (RAM) بسعة 4 غيغابايت أو 6 غيغابايت. تضمن الإدارة السليمة للذاكرة إمكانية الوصول إلى لعبتك واستجابتها على جميع مستويات الأجهزة بدون الحاجة إلى حِزم مواد عرض منفصلة ومعقّدة.
فهم الذاكرة في Android
لتصميم استراتيجيات فعّالة لإدارة الذاكرة، يجب أن يفهم المطوّرون كيفية إدارة نظام Android الأساسي للذاكرة الفعلية وكيفية قياسه للبصمة النشطة للعبة.
المفاهيم الأساسية لذاكرة Android
للاطّلاع على المفاهيم الأساسية المتعلّقة بإدارة الذاكرة على مستوى المنصة، يُرجى مراجعة مستندات نظرة عامة على إدارة الذاكرة الرسمية. يتناول هذا المرجع أربعة جوانب معمارية:
- نظرة عامة على الذاكرة: يستخدم Android ميزتَي التنقّل بين الصفحات وتعيين الذاكرة (mmap) لإدارة ذاكرة الوصول العشوائي. لا يتيح نظام التشغيل Android استخدام ملف مبادلة تقليدي على القرص، بل يعتمد على ضغط الصفحات (باستخدام zRAM) واستعادة الصفحات لإخلاء مساحة في الذاكرة الفعلية.
- تخصيص الذاكرة بين العمليات: يشارك Android ذاكرة الوصول العشوائي (RAM) على مستوى النظام بأكمله. ويخصّص هذا النظام مساحات تخزين مؤقتة معيّنة لتنفيذ الأجهزة الافتراضية Dalvik أو ART، مع السماح لبيئات التطوير الأصلية (مثل محرّكات الألعاب بلغة C++) بطلب الذاكرة من مساحة التخزين المؤقتة للنظام الأصلي.
- إدارة ذاكرة التطبيقات: يعمل نظام Android وفقًا لنموذج العمليات المتعدّدة، ويتوقّع من التطبيقات مراقبة حالة مراحل نشاطها بشكل ديناميكي وتحرير الموارد غير الضرورية طوعًا (مثل الرسومات والصور النقطية غير المخزَّنة مؤقتًا) للحفاظ على سلامة النظام.
- نظرة عامة على العمليات وسلاسل المحادثات: يصنّف النظام العمليات في تسلسل هرمي استنادًا إلى مستوى ظهورها وأهميتها الحالية بالنسبة إلى المستخدم، ويحدّد العمليات التي يتم الإبقاء عليها والعمليات التي يتم إنهاؤها أولاً في حالات انخفاض الذاكرة.
مقياس إجمالي استهلاك الذاكرة
يقيّم "محدِّد الذاكرة" في Android 17 على مستوى النظام الأساسي استهلاك العمليات باستخدام إجمالي استهلاك الذاكرة بدلاً من إجمالي حجم الذاكرة المقيمة (RSS) أو حجم الذاكرة الافتراضية.
إجمالي استهلاك الذاكرة = ذاكرة RSS المجهولة (RssAnon) + مساحة الإبدال غير المضغوطة (VmSwap)
لمنع الألعاب من تجاوز حدود المنصة، عليك فهم ما تمثّله هذه المقاييس بالضبط على مستوى النظام. لمزيد من المعلومات حول هذه المقاييس وتخصيصات ذاكرة الوصول العشوائي (RAM) الفعلية وكيفية التعامل مع الصفحات المستندة إلى الملفات، يُرجى الاطّلاع على فهم مقاييس RSS ومقاييس Swap في دليل مراقبة استخدام الذاكرة.
قيود الذاكرة
للحفاظ على استقرار النظام وضمان عدم استهلاك التطبيقات لموارد زائدة، يدير نظام Android الأساسي حدود الذاكرة للعمليات قيد التشغيل.
ميزة "محدِّد الذاكرة" في Android 17 والإصدارات الأحدث
يفرض الإصدار 17 من Android (مستوى واجهة برمجة التطبيقات 37) والإصدارات الأحدث حدودًا صارمة على الذاكرة لكل تطبيق باستخدام الإصدار 2 من Linux cgroup لمنع التطبيقات الفردية من التسبب في عدم استقرار النظام بالكامل. لمزيد من التفاصيل حول التنفيذ الفني، يُرجى الاطّلاع على دليل محدِّد الذاكرة في مشروع Android المفتوح المصدر (AOSP) ومنشور المدونة "إعطاء الأولوية لكفاءة الذاكرة: خطوات أساسية لنظام التشغيل Android 17".
- الآلية: تراقب ميزة "محدِّد الذاكرة" جميع عمليات التطبيقات وتخصّص الحدود القصوى بشكل ديناميكي استنادًا إلى حالة دورة حياة العملية:
- العمليات المرئية (في المقدّمة): من المتوقّع أن تعمل عمليات التطبيق التي تعرض حاليًا واجهة مستخدم على تشغيل مجموعة عمل أكبر من الموارد، ويتم منحها حدًا أكبر.
- العمليات غير المرئية (الخلفية أو الخدمات): تقتصر عمليات التطبيق التي تؤدي عملاً نشطًا بدون عرض واجهة مستخدم على ميزانية أكثر صرامة وتقييدًا.
- سمات النواة: تعتمد الخدمة على سمتَين رئيسيتَين:
memory.high: حدّ أقصى مرن وعند تجاوز هذا الحد، تعمل النواة على تقييد العملية ومحاولة استعادة الذاكرة بقوة. وقد يؤدي ذلك إلى انخفاض أداء اللعبة.memory.swap.max: يدير هذا الإعداد الحد الأقصى لمساحة التبديل أو zRAM التي يمكن للعملية استخدامها.
- سلوك الإنهاء: إذا استمرت إحدى العمليات في تخصيص ذاكرة مجهولة المصدر
بعد تجاوز
memory.highواستنفاد سعة التبديل، ستفشل عمليات التخصيص، ويُنهي نظام التشغيل العملية تلقائيًا. يتم تسجيل عملية الإنهاء هذه باستخدامApplicationExitInfoضمن سبب الخروج Memory Limiter (متاح بدءًا من الإصدار Android 17، 26Q4).
حدود جديدة للذاكرة في مؤشرات Play Console الحيوية
لمساعدة المطوّرين في تحديد مشاكل الذاكرة بشكل استباقي، يقدّم Google Play مقاييس جديدة في "مؤشرات Android الحيوية" ضمن Play Console. تتتبّع Play Console استهلاك الذاكرة في الشريحة المئوية التسعين (P90) من ذاكرة RSS المجهولة + مساحة الإبدال في جلسات لعبتك لتحديد القيم الشاذة للغاية.
يتم تحديد الحدّ الأقصى للتحذير وإجراء التنفيذ استنادًا إلى سعة ذاكرة الوصول العشوائي (RAM) الفعلية للجهاز وحالات العمليات. تنطبق هذه الحدود في مرحلتَين مختلفتَين.
للحصول على إرشادات مفصّلة وحدود الذاكرة، يُرجى الاطّلاع على مؤشرات Android الحيوية - ما هي معايير تحديد الأداء السيئ؟.
خدمات يلاحظها المستخدم
"الخدمات الملحوظة" هي عمليات مهمة في الخلفية يعتبرها نظام Android ملحوظة للمستخدم. تشمل هذه الحالة جميع العمليات التي يتم تنفيذها:
- الخدمات التي تعمل في المقدّمة (FGS)
- المهام المُعجَّلة
- مهام نقل البيانات التي يبدأها المستخدم
- الخدمات المرتبطة بالنظام أو الخدمات المرتبطة بتطبيقات أخرى
بما أنّ الخدمات الملحوظة مصمَّمة للمهام المهمة التي تستغرق وقتًا طويلاً في الخلفية، فهي معرّضة بشكل كبير لتسرُّب الذاكرة التراكمي في مراحل النشاط. تتعامل حدود الذاكرة في نظام Android الأساسي مع هذه الحالة على أنّها ليست في المقدّمة، ما يعني أنّه إذا كانت لعبتك تعمل في الخلفية ولكنّها تستمر في تشغيل خدمة ملحوظة، فإنّها تخضع لحدود الذاكرة الأكثر صرامة في الخلفية أو الخدمة الموضّحة في صفحة مركز مساعدة Play. يجب أن تعمل الألعاب على تقليص الأصول غير الضرورية بشكل كبير عند الانتقال من المقدّمة إلى حالة "الخدمة الملحوظة" في الخلفية.
متطلبات R8
لتقليل حجم الرمز الثانوي وتقليل عبء معالجة Java الأساسية، يقيّم Google Play Console تحسين الرمز كجزء من إرشادات جودة التطبيق. لمزيد من المعلومات عن متطلبات التحسين والحدود التي تنطبق على الألعاب، يُرجى الاطّلاع على تحسين رمز DEX في مستندات "مؤشرات Android الحيوية".
لضبط R8 في مشروع Android عادي، اتّبِع دليل تفعيل تحسين التطبيق. لتفعيل إعدادات التصغير والتحسين المتقدّمة، يُرجى الاطّلاع على مقالة استخدام R8 في الوضع الكامل. لتحديد القواعد التي تمنع R8 من إخفاء فئات أو إزالة الرموز البرمجية غير المستخدَمة، يمكنك استخدام أداة تحليل إعدادات R8.
إذا كنت تستخدم محرّك ألعاب، يختلف سلوك R8 التلقائي حسب المحرّك والإصدار:
- Unity: تكون ميزة تصغير الرمز غير مفعَّلة تلقائيًا، لذا عليك تفعيلها في إعدادات مشروعك. لمزيد من المعلومات حول الإصدارات المتوافقة وخطوات الضبط، يُرجى الاطّلاع على مقالة تقليص حجم رمز Unity وتحسينه باستخدام R8.
- Unreal Engine: بدءًا من الإصدار 4.25 من Unreal Engine، يتم تفعيل أداة R8 تلقائيًا في إصدارات البرامج، ما يتطلّب منك إدارة قواعد الاحتفاظ بالرموز لجسور JNI والمكوّنات الإضافية. لمزيد من المعلومات حول تفاصيل الإصدار وإعدادات UPL، يُرجى الاطّلاع على تقليص حجم رمز Unreal Engine وتحسينه باستخدام R8.
متطلبات الصور النقطية
تمثّل الصور النقطية جزءًا كبيرًا من استخدام الذاكرة في الألعاب الحديثة العالية الدقة. بما أنّ بيانات وحدات بكسل Bitmap يتم تخزينها مباشرةً في الذاكرة المؤقتة الأصلية غير المُدارة على نظام التشغيل Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) والإصدارات الأحدث، يمكن أن يؤدي تحميل الصور غير المحسّنة إلى تجاوز حدود الذاكرة المسموح بها في النظام الأساسي. للاطّلاع على أفضل الممارسات المتعلّقة بتغيير حجم الصور وتخزينها مؤقتًا، يُرجى مراجعة تحسين استخدام الصور.
مراقبة استخدام الذاكرة
لتحسين ذاكرة لعبتك بفعالية، عليك أولاً فهم كيفية قياس نظام Android الأساسي لبصمتها. يعدّل Android 17 مقياس الذاكرة لتتبُّع مجموع ذاكرة RSS المجهولة (RssAnon) ومساحة الإبدال غير المضغوطة (VmSwap)، باستثناء الذاكرة المستندة إلى الملفات أو الذاكرة الخاصة بوحدة معالجة الرسومات. يوضّح هذا الدليل بالتفصيل
كيفية استخدام الأدوات على مستوى النظام، مثل Perfetto وmeminfo، وتنفيذ
واجهات برمجة التطبيقات التشخيصية، مثل ProfilingManager وonTrimMemory، واستخراج
عمليات تخصيص الذاكرة الدقيقة في Unity وUnreal Engine. تعرَّف على كيفية
تحليل أداء لعبتك بدقة وتجنُّب حالات التقطُّع في الأداء المرتبطة
بالاستطلاع التقليدي للذاكرة أثناء التشغيل.
لمزيد من المعلومات، يُرجى الاطّلاع على مراقبة استخدام الذاكرة.
استراتيجيات تقليل استخدام الذاكرة
على الرغم من أنّ محرّكات الألعاب تسهّل عملية التطوير من عدّة منصات، فإنّ طريقة معالجتها التلقائية للذاكرة قد تؤدي إلى تجاوز حدود الذاكرة على مستوى نظام التشغيل. توضّح هذه الصفحة بالتفصيل خطوات التحسين العملية المصمّمة خصيصًا لمحركَي Unity وUnreal Engine. تعرَّف على سبب حدوث حالات توقُّف تام في Unity عند الاعتماد على onTrimMemory المستندة إلى Java، وكيفية استخدام الاستدعاءات في إحدى مراحل النشاط الأصلية بدلاً من ذلك. ستتعرّف أيضًا على أهم التحسينات على مستوى مواد العرض، مثل استخدام ضغط الزخرفة ASTC 8x8 وضبط عمليات إلغاء تحميل مواد العرض، للحفاظ على سلاسة تشغيل لعبتك على جميع مستويات الأجهزة.
لمزيد من المعلومات، يُرجى الاطّلاع على مقالة تقليل استخدام الذاكرة.