ضبط تتبُّع النظام

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

إعداد تتبُّع نظام مستند إلى الألعاب

تتوفّر أداة Systrace بطريقتَين:

‫Systrace هي أداة منخفضة المستوى تعمل على ما يلي:

  • توفير معلومات فعلية: تسجّل أداة Systrace الناتج مباشرةً من النواة، لذا تكون المقاييس التي تسجّلها مطابقة تقريبًا لتلك التي يتم تسجيلها من خلال سلسلة من طلبات النظام.
  • استهلاك عدد قليل من الموارد: تفرض أداة Systrace حملًا منخفضًا جدًا على الجهاز، عادةً أقل من %1، لأنّها تنقل البيانات إلى مخزن مؤقت في الذاكرة.

الإعدادات المثالية

من المهم تقديم مجموعة معقولة من الوسيطات للأداة:

  • الفئات: أفضل مجموعة من الفئات التي يجب تفعيلها لتتبُّع نظام يستند إلى الألعاب هي: {sched وfreq وidle وam وwm وgfx وview وsync وbinder_driver وhal وdalvik}.
  • حجم ذاكرة التخزين المؤقت: القاعدة العامة هي أنّ حجم ذاكرة التخزين المؤقت البالغ 10 ميغابايت لكل نواة وحدة معالجة مركزية يتيح تتبُّعًا لمدة 20 ثانية تقريبًا. على سبيل المثال، إذا كان الجهاز يحتوي على وحدتَي معالجة مركزية رباعية النواة (8 نوى إجمالاً)، ستكون القيمة المناسبة التي يجب تمريرها إلى برنامج systrace هي 80,000 كيلوبايت (80 ميغابايت).

    إذا كانت لعبتك تجري الكثير من عمليات تبديل السياق، عليك زيادة حجم المخزن المؤقت إلى 15 ميغابايت لكل نواة وحدة معالجة مركزية.

  • الأحداث المخصّصة: إذا حدّدت أحداثًا مخصّصة لتسجيلها في لعبتك، فعِّل العلامة -a، ما يسمح لأداة Systrace بتضمين هذه الأحداث المخصّصة في تقرير الإخراج.

إذا كنت تستخدم برنامج سطر الأوامر systrace، استخدِم الأمر التالي لتسجيل تتبُّع للنظام يطبّق أفضل الممارسات على مجموعة الفئات وحجم المخزن المؤقت والأحداث المخصّصة:

python systrace.py -a com.example.myapp -b 80000 -o my_systrace_report.html \
  sched freq idle am wm gfx view sync binder_driver hal dalvik

إذا كنت تستخدم تطبيق Systrace على جهاز، أكمِل الخطوات التالية لتسجيل تتبُّع النظام الذي يطبّق أفضل الممارسات لمجموعة الفئات وحجم المخزن المؤقت والأحداث المخصّصة:

  1. فعِّل الخيار تتبُّع التطبيقات التي يمكن تصحيح أخطائها.

    لاستخدام هذا الإعداد، يجب أن يتوفّر في الجهاز مساحة 256 ميغابايت أو 512 ميغابايت (حسب ما إذا كانت وحدة المعالجة المركزية تحتوي على 4 أو 8 أنوية)، ويجب أن تتوفّر كل قطعة من الذاكرة بحجم 64 ميغابايت كجزء متجاور.

  2. اختَر الفئات، ثم فعِّل الفئات في القائمة التالية:

    • ‫am: مدير النشاط
    • ‫binder_driver: برنامج تشغيل Binder Kernel
    • ‫dalvik: Dalvik VM
    • ‫freq: معدّل تكرار وحدة المعالجة المركزية
    • ‫gfx: الرسومات
    • ‫hal: وحدات الأجهزة
    • ‫idle: وقت عدم نشاط وحدة المعالجة المركزية
    • sched: جدولة وحدة المعالجة المركزية
    • ‫sync: المزامنة
    • ‫view: عرض النظام
    • wm: مدير النوافذ
  3. فعِّل خيار تسجيل التتبُّع.

  4. حمِّل لعبتك.

  5. نفِّذ التفاعلات في لعبتك التي تتوافق مع أسلوب اللعب الذي تريد قياس أداء الجهاز فيه.

  6. بعد مواجهة سلوك غير مرغوب فيه في لعبتك بفترة قصيرة، أوقِف تتبُّع النظام.

لقد سجّلت إحصاءات الأداء اللازمة لتحليل المشكلة بشكل أكبر.

لتوفير مساحة القرص، تحفظ عمليات تتبُّع النظام على الجهاز فقط الملفات بتنسيق مضغوط (*.ctrace). ولإلغاء ضغط هذا الملف عند إنشاء تقرير، استخدِم برنامج سطر الأوامر وضمِّن الخيار --from-file:

python systrace.py --from-file=/data/local/traces/my_game_trace.ctrace \
  -o my_systrace_report.html

تحسين مجالات أداء محدّدة

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

سرعة التحميل

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

  • استخدام طريقة التحميل الكسول: إذا كنت تستخدم مواد العرض نفسها في مشاهد أو مستويات متتالية في لعبتك، حمِّل مواد العرض هذه مرة واحدة فقط.
  • تقليل حجم مواد العرض: بهذه الطريقة، يمكنك تجميع إصدارات غير مضغوطة من مواد العرض هذه مع حزمة APK الخاصة بلعبتك.
  • استخدام طريقة ضغط فعّالة من حيث استخدام مساحة التخزين على القرص: ومن الأمثلة على هذه الطريقة zlib.
  • استخدِم IL2CPP بدلاً من mono. (ينطبق فقط إذا كنت تستخدم Unity). توفّر IL2CPP أداءً أفضل لتنفيذ نصوص C# البرمجية.
  • اجعل لعبتك متوافقة مع تعدد مؤشرات الترابط. لمزيد من التفاصيل، يُرجى الاطّلاع على القسم اتّساق معدّل عرض اللقطات في الثانية.

اتّساق عدد اللقطات في الثانية

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

تعدّد سلاسل التعليمات

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

تعرض أداة Systrace الموضّحة في الشكل 1 سلوكًا نموذجيًا للعبة يتم تشغيلها على وحدة معالجة مركزية واحدة فقط في كل مرة:

مخطّط لسلاسل المحادثات
ضمن سجلّ تتبُّع النظام

الشكل 1. تقرير Systrace للعبة ذات سلسلة محادثات واحدة

لتحسين أداء لعبتك، اجعلها تستخدم عدة سلاسل محادثات. عادةً، يكون أفضل نموذج هو استخدام سلسلتَي تنفيذ:

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

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

يمكنك أيضًا إجراء بعض التغييرات الخاصة بمحرك الألعاب لتحسين أداء اللعبة في ما يتعلق بتعدد مؤشرات الترابط:

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

بعد تطبيق هذه التغييرات، من المفترض أن ترى لعبتك تستخدم وحدتَي معالجة مركزية (CPU) على الأقل في الوقت نفسه، كما هو موضّح في الشكل 2:

مخطّط لسلاسل المحادثات
ضمن سجلّ تتبُّع النظام

الشكل 2. تقرير Systrace للعبة متعددة مؤشرات الترابط

تحميل عنصر في واجهة المستخدم

مخطّط بياني لمجموعة
  إطارات ضمن تتبُّع نظام
الشكل 3. تقرير Systrace للعبة تعرض عشرات عناصر واجهة المستخدم في الوقت نفسه

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

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

من الأهداف الجيدة تقليل وقت تعديل واجهة المستخدم إلى 2 أو 3 ملّي ثانية. يمكنك إجراء هذه التعديلات السريعة من خلال تنفيذ عمليات تحسين مشابهة لما يلي:

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

استهلاك الطاقة

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

في كثير من الحالات، تكون هذه المجموعة غير المرغوب فيها من درجات الحرارة واستهلاك الطاقة مرتبطة بطريقة توزيع عبء العمل في لعبتك على وحدات المعالجة المركزية بالجهاز. لزيادة كفاءة استهلاك الطاقة في لعبتك، اتّبِع أفضل الممارسات الموضّحة في الأقسام التالية.

إبقاء سلاسل التعليمات التي تستهلك الكثير من الذاكرة على وحدة معالجة مركزية واحدة

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

تأجيل العمليات القصيرة المدة إلى وحدات معالجة مركزية ذات طاقة أقل

تعرف معظم محركات الألعاب، بما في ذلك Unity، كيفية تأجيل عمليات سلسلة الوحدات العاملة (worker thread) إلى وحدة معالجة مركزية مختلفة عن السلسلة الرئيسية للعبتك. ومع ذلك، لا يمكن للمحرّك التعرّف على بنية الجهاز المحدّدة، ولا يمكنه توقّع عبء العمل في لعبتك كما يمكنك أنت.

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

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

مخطّط لسلاسل المحادثات
ضمن سجلّ تتبُّع النظام

الشكل 4. تقرير Systrace يعرض عملية غير مثالية لتوزيع سلاسل التعليمات على وحدات المعالجة المركزية في الجهاز

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

تدرج معظم الأجهزة وحدات المعالجة المركزية البطيئة قبل وحدات المعالجة المركزية السريعة، ولكن لا يمكنك افتراض أنّ نظام التشغيل على الشريحة (SOC) في جهازك يستخدم هذا الترتيب. للتحقّق من ذلك، شغِّل أوامر مشابهة لتلك الموضّحة في رمز اكتشاف بنية وحدة المعالجة المركزية على GitHub.

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

#include <sched.h>
#include <sys/types.h>
#include <unistd.h>

pid_t my_pid; // PID of the process containing your thread.

// Assumes that cpu0, cpu1, cpu2, and cpu3 are the "slow CPUs".
cpu_set_t my_cpu_set;
CPU_ZERO(&my_cpu_set);
CPU_SET(0, &my_cpu_set);
CPU_SET(1, &my_cpu_set);
CPU_SET(2, &my_cpu_set);
CPU_SET(3, &my_cpu_set);
sched_setaffinity(my_pid, sizeof(cpu_set_t), &my_cpu_set);

الإجهاد الحراري

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

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

أولاً، عليك تعريف عنصر PowerManager وتهيئته في طريقة onCreate(). أضِف أداة معالجة حالة حرارية إلى العنصر.

Kotlin

class MainActivity : AppCompatActivity() {
    lateinit var powerManager: PowerManager

    override fun onCreate(savedInstanceState: Bundle?) {
        powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
        powerManager.addThermalStatusListener(thermalListener)
    }
}

Java

public class MainActivity extends AppCompatActivity {
    PowerManager powerManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
        powerManager.addThermalStatusListener(thermalListener);
    }
}

حدِّد الإجراءات التي يجب اتّخاذها عندما يرصد المستمع تغييرًا في الحالة. إذا كانت لعبتك تستخدم C/C++‎، أضِف رمزًا برمجيًا إلى مستويات حالة الحرارة في onThermalStatusChanged() من أجل استدعاء رمز اللعبة الأصلي باستخدام JNI أو استخدِم Thermal API الأصلي.

Kotlin

val thermalListener = object : PowerManager.OnThermalStatusChangedListener() {
    override fun onThermalStatusChanged(status: Int) {
        when (status) {
            PowerManager.THERMAL_STATUS_NONE -> {
                // No thermal status, so no action necessary
            }

            PowerManager.THERMAL_STATUS_LIGHT -> {
                // Add code to handle light thermal increase
            }

            PowerManager.THERMAL_STATUS_MODERATE -> {
                // Add code to handle moderate thermal increase
            }

            PowerManager.THERMAL_STATUS_SEVERE -> {
                // Add code to handle severe thermal increase
            }

            PowerManager.THERMAL_STATUS_CRITICAL -> {
                // Add code to handle critical thermal increase
            }

            PowerManager.THERMAL_STATUS_EMERGENCY -> {
                // Add code to handle emergency thermal increase
            }

            PowerManager.THERMAL_STATUS_SHUTDOWN -> {
                // Add code to handle immediate shutdown
            }
        }
    }
}

Java

PowerManager.OnThermalStatusChangedListener thermalListener =
    new PowerManager.OnThermalStatusChangedListener () {

    @Override
    public void onThermalStatusChanged(int status) {

        switch (status)
        {
            case PowerManager.THERMAL_STATUS_NONE:
                // No thermal status, so no action necessary
                break;

            case PowerManager.THERMAL_STATUS_LIGHT:
                // Add code to handle light thermal increase
                break;

            case PowerManager.THERMAL_STATUS_MODERATE:
                // Add code to handle moderate thermal increase
                break;

            case PowerManager.THERMAL_STATUS_SEVERE:
                // Add code to handle severe thermal increase
                break;

            case PowerManager.THERMAL_STATUS_CRITICAL:
                // Add code to handle critical thermal increase
                break;

            case PowerManager.THERMAL_STATUS_EMERGENCY:
                // Add code to handle emergency thermal increase
                break;

            case PowerManager.THERMAL_STATUS_SHUTDOWN:
                // Add code to handle immediate shutdown
                break;
        }
    }
};

وقت الاستجابة بين اللمس والعرض

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

لتحديد ما إذا كان بإمكانك تحسين معدّل عرض اللقطات في لعبتك، يُرجى اتّباع الخطوات التالية:

  1. إنشاء تقرير Systrace يتضمّن الفئتَين gfx وinput وتشمل هذه الفئات مقاييس مفيدة بشكل خاص لتحديد وقت استجابة اللمس إلى العرض.
  2. راجِع القسم SurfaceView في تقرير Systrace. يؤدي المخزن المؤقت المكتظ إلى تذبذب عدد عمليات رسم المخزن المؤقت المعلقة بين 1 و2، كما هو موضح في الشكل 5:

    مخطّط بياني لقائمة انتظار المخزن المؤقت ضمن سجلّ تتبُّع النظام

    الشكل 5. تقرير Systrace يعرض مخزنًا مؤقتًا ممتلئًا بشكل مفرط، ويكون ممتلئًا بشكل دوري لدرجة لا يمكنه قبول أوامر الرسم

للتخفيف من حدة هذا التفاوت في سرعة عرض اللقطات، أكمل الإجراءات الموضّحة في الأقسام التالية:

دمج واجهة برمجة التطبيقات Android Frame Pacing API في لعبتك

تساعدك واجهة برمجة التطبيقات Android Frame Pacing API في تنفيذ عمليات تبديل الإطارات وتحديد فاصل زمني للتبديل، ما يتيح للعبتك الحفاظ على معدّل إطارات أكثر ثباتًا.

تقليل دقة مواد العرض غير الخاصة بواجهة المستخدم في لعبتك

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

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

سلاسة العرض

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

مخطّط بياني للإطارات التي لا تتضمّن نافذة Vsync لأنّها بدأت الرسم متأخرة جدًا

الشكل 6. تقرير Systrace يوضّح كيف يمكن أن تفوّت اللقطة حدث Vsync

إذا بدأ عرض إطار متأخرًا جدًا، حتى ولو ببضع أجزاء من الثانية، قد لا يتم عرضه في نافذة العرض التالية. بعد ذلك، يجب أن ينتظر الإطار حتى تتم مزامنته مع الإشارة العمودية التالية ليتم عرضه (33 ملي ثانية عند تشغيل لعبة بمعدل 30 إطارًا في الثانية)، ما يؤدي إلى حدوث تأخير ملحوظ من منظور اللاعب.

ولحلّ هذه المشكلة، استخدِم Android Frame Pacing API الذي يعرض دائمًا إطارًا جديدًا على موجة VSync.

حالة الذاكرة

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

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

لمزيد من المعلومات، يُرجى الاطّلاع على لمحة عن إدارة الذاكرة.

حالة سلسلة المحادثات

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

مخطّط بياني لتقرير Systrace

الشكل 7. تقرير Systrace يعرض كيف يؤدي اختيار سلسلة محادثات إلى أن يعرض التقرير ملخّصًا للحالة الخاصة بسلسلة المحادثات هذه

كما يوضّح الشكل 7، قد تجد أنّ سلاسل التعليمات البرمجية في لعبتك لا تكون في حالة "قيد التشغيل" أو "قابلة للتشغيل" بالقدر المطلوب. تعرض القائمة التالية عدة أسباب شائعة قد تؤدي إلى انتقال سلسلة محادثات معيّنة بشكل دوري إلى حالة غير عادية:

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

مراجع إضافية

لمزيد من المعلومات حول تحسين أداء لعبتك، اطّلِع على المراجع الإضافية التالية:

الفيديوهات