مدیریت موثر حافظه در بازی ها

در پلتفرم اندروید، سیستم سعی می‌کند تا حد امکان از حافظه سیستم (RAM) استفاده کند و بهینه‌سازی‌های مختلف حافظه را انجام می‌دهد تا در صورت نیاز فضا را آزاد کند. این بهینه‌سازی‌ها می‌توانند بر روی بازی شما تأثیر منفی بگذارند، چه با کند کردن آن یا از بین بردن آن. می توانید در مبحث تخصیص حافظه در میان فرآیندها درباره این بهینه سازی ها بیشتر بدانید.

این صفحه مراحلی را توضیح می‌دهد که می‌توانید برای جلوگیری از تأثیر شرایط حافظه کم بر بازی خود انجام دهید.

پاسخ به onTrimMemory()

این سیستم از onTrimMemory() استفاده می کند تا برنامه شما را از رویدادهای چرخه حیات مطلع کند که فرصت خوبی برای برنامه شما فراهم می کند تا داوطلبانه مصرف حافظه خود را کاهش دهد و از کشته شدن توسط قاتل کم حافظه (LMK) جلوگیری کند تا حافظه را برای سایر برنامه ها آزاد کند.

اگر برنامه شما در پس‌زمینه کشته شود، دفعه بعد که کاربر برنامه شما را راه‌اندازی می‌کند، شروع سردی آهسته را تجربه می‌کند. برنامه‌هایی که هنگام رفتن به پس‌زمینه، مصرف حافظه خود را کاهش می‌دهند، کمتر در پس‌زمینه کشته می‌شوند.

هنگام پاسخ دادن به رویدادهای برش، بهتر است تخصیص حافظه بزرگی را منتشر کنید که فوراً مورد نیاز نیستند و می‌توانند در صورت تقاضا بازسازی شوند. به عنوان مثال، اگر برنامه شما دارای یک کش بیت مپ است که از تصاویر فشرده ذخیره شده محلی رمزگشایی شده است، اغلب ایده خوبی است که در پاسخ به TRIM_MEMORY_UI_HIDDEN ، این حافظه پنهان را برش داده یا پاک کنید.

کاتلین

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.
        }
    }
}

جاوا

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.
            }
        }
    }
}

سی شارپ

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 توسعه داده شد که یادآوری و دقت بسیار بالاتری در پیش‌بینی LMK‌های قریب‌الوقوع دارد. API با تخمین مقدار منابع حافظه در حال استفاده، و سپس اطلاع دادن به برنامه در صورت تجاوز از آستانه های خاص، به این امر دست می یابد. API همچنین می تواند درصد تخمینی استفاده از حافظه را مستقیماً به برنامه شما گزارش دهد. می توانید از Memory Advice API به عنوان جایگزینی برای رویدادهای onTrimMemory برای مدیریت حافظه استفاده کنید.

برای استفاده از Memory Advice API از راهنمای شروع استفاده کنید.

در مورد بودجه حافظه محافظه کار باشید

حافظه بودجه را محافظه کارانه بسازید تا از تمام شدن حافظه جلوگیری کنید. برخی از مواردی که باید در نظر گرفته شود شامل موارد زیر است:

  • اندازه رم فیزیکی : بازی ها اغلب بین ¼ تا ½ رم فیزیکی دستگاه استفاده می کنند.
  • حداکثر اندازه zRAM : zRAM بیشتر به این معنی است که بازی به طور بالقوه حافظه بیشتری برای تخصیص دارد. این مقدار می تواند بر اساس دستگاه متفاوت باشد. به دنبال SwapTotal در /proc/meminfo بگردید تا این مقدار را پیدا کنید.
  • استفاده از حافظه سیستم‌عامل : دستگاه‌هایی که رم بیشتری را برای پردازش‌های سیستم تعیین می‌کنند، حافظه کمتری برای بازی شما باقی می‌گذارند. این سیستم قبل از اینکه فرآیندهای سیستم را از بین ببرد، روند بازی شما را از بین می برد.
  • استفاده از حافظه برنامه‌های نصب‌شده : بازی خود را روی دستگاه‌هایی که برنامه‌های زیادی نصب شده‌اند آزمایش کنید. برنامه های رسانه های اجتماعی و چت باید دائما اجرا شوند و بر میزان حافظه آزاد تأثیر بگذارند.

اگر نمی توانید متعهد به بودجه محافظه کارانه حافظه باشید، رویکرد انعطاف پذیرتری را در پیش بگیرید. اگر سیستم با مشکلات حافظه کم مواجه شد، مقدار حافظه ای را که بازی استفاده می کند کاهش دهید. به عنوان مثال، در پاسخ به onTrimMemory() ، بافت‌های با وضوح پایین‌تر را اختصاص دهید یا سایه‌زن‌های کمتری ذخیره کنید. این رویکرد پویا برای تخصیص حافظه نیازمند کار بیشتر توسعه دهنده، به ویژه در مرحله طراحی بازی است.

از کوبیدن خودداری کنید

Thrashing زمانی اتفاق می‌افتد که حافظه آزاد کم باشد، اما آنقدر کم نیست که بازی را از بین ببرد. در این شرایط، kswapd صفحاتی را که بازی هنوز به آنها نیاز دارد را بازیابی کرده است، بنابراین سعی می کند صفحات را از حافظه بارگذاری مجدد کند. فضای کافی وجود ندارد، بنابراین صفحات مرتباً مبادله می شوند (تبادل مداوم). ردیابی سیستم این وضعیت را به عنوان یک رشته گزارش می دهد که kswapd به طور مداوم در آن اجرا می شود.

یکی از علائم کوبیدن زمان فریم طولانی است - احتمالاً یک ثانیه یا بیشتر. برای حل این وضعیت، ردپای حافظه بازی را کاهش دهید.

از ابزارهای موجود استفاده کنید

اندروید مجموعه ای از ابزارها برای کمک به درک نحوه مدیریت حافظه توسط سیستم دارد.

Meminfo

این ابزار آمار حافظه را جمع آوری می کند تا نشان دهد که چه مقدار حافظه PSS اختصاص یافته است و چه دسته هایی از آن استفاده شده است.

آمار meminfo را به یکی از روش های زیر چاپ کنید:

  • از دستور adb shell dumpsys meminfo package-name استفاده کنید.
  • از تماس MemoryInfo از Android Debug API استفاده کنید.

آمار PrivateDirty میزان RAM داخل فرآیند را نشان می دهد که نمی توان آن را در دیسک صفحه بندی کرد و با هیچ فرآیند دیگری به اشتراک گذاشته نمی شود. بخش عمده ای از این مقدار زمانی در دسترس سیستم قرار می گیرد که این فرآیند از بین برود.

نقاط ردیابی حافظه

نقاط ردیابی حافظه میزان حافظه RSS مورد استفاده بازی شما را ردیابی می کنند. محاسبه میزان مصرف حافظه RSS بسیار سریعتر از محاسبه مصرف PSS است. از آنجایی که محاسبه سریع‌تر است، RSS جزئیات دقیق‌تری را در تغییرات اندازه حافظه نشان می‌دهد تا اندازه‌گیری دقیق‌تری از حداکثر استفاده از حافظه داشته باشد. بنابراین، تشخیص اوج هایی که می توانند باعث از بین رفتن حافظه بازی شوند، آسان تر است.

پرفتو و آثار طولانی

Perfetto مجموعه ای از ابزارها برای جمع آوری اطلاعات عملکرد و حافظه روی یک دستگاه و نمایش در یک رابط کاربری مبتنی بر وب است. از ردیابی های طولانی خودسرانه پشتیبانی می کند تا بتوانید نحوه تغییر RSS در طول زمان را مشاهده کنید. همچنین می توانید پرس و جوهای SQL را روی داده هایی که برای پردازش آفلاین تولید می کند، صادر کنید. ردیابی طولانی را از برنامه System Tracing فعال کنید. مطمئن شوید که دسته حافظه: حافظه برای ردیابی فعال باشد.

heappropd

heapprofd یک ابزار ردیابی حافظه است که بخشی از Perfetto است. این ابزار می تواند با نشان دادن محل تخصیص حافظه با استفاده از malloc به شما کمک کند نشت حافظه را پیدا کنید. heapprofd می توان با استفاده از اسکریپت پایتون شروع کرد و چون این ابزار سربار کمی دارد، مانند ابزارهای دیگر مانند Malloc Debug بر عملکرد تأثیر نمی گذارد.

گزارش اشکال

bugreport ابزاری است برای یافتن اینکه آیا بازی شما به دلیل اتمام حافظه از کار افتاده است یا خیر. خروجی ابزار بسیار دقیق تر از استفاده از logcat است. این برای اشکال زدایی حافظه مفید است زیرا نشان می دهد که آیا بازی شما به دلیل تمام شدن حافظه از کار افتاده یا توسط LMK کشته شده است.

برای اطلاعات بیشتر، به ضبط و خواندن گزارش‌های اشکال مراجعه کنید.