ניהול יעיל של הזיכרון במשחקים

בפלטפורמת 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())
    }
}

שימוש בגרסת הבטא של Memory Adwise API

ה-Memory Adwise API פותח ל-onTrimMemory, שיש לו רמת זיכרון גבוהה יותר ורמת דיוק גבוהה יותר חיזוי של מערכות LMK קרובות. ה-API משיג זאת על ידי הערכת כמות במשאבי זיכרון שנמצאים בשימוש, ולאחר מכן הודעות לאפליקציה כאשר פונקציות מסוימות יש חריגה מערכי הסף. ה-API יכול גם לדווח על האחוז המשוער של של הזיכרון ישירות באפליקציה. אפשר להשתמש ב-Memory Adwise API בתור חלופה ל- onTrimMemory אירועים לצורך ניהול זיכרון.

כדי להשתמש ב-Memory Advantage API צריך להשתמש המדריך לתחילת העבודה.

מקפידים על יכולות שמרניות של תקציבי זיכרון

תקציב תקציב נמוך באופן שמרני כדי למנוע מחסור בזיכרון. פריטים מסוימים כדאי לכלול את הנושאים הבאים:

  • גודל ה-RAM הפיזי: לעיתים קרובות, במשחקים נעשה שימוש ב-1⁄4 מ-1⁄2 מהזיכרון הפיזי. כמות ה-RAM במכשיר.
  • גודל zRAM מקסימלי: אם נפח האחסון גדול יותר, יכול להיות שלמשחק יהיה יותר זיכרון להקצות. הסכום הזה יכול להשתנות בהתאם למכשיר. צריך לחפש את SwapTotal ב- /proc/meminfo כדי למצוא את הערך הזה.
  • השימוש בזיכרון של מערכת ההפעלה: מכשירים שמקצים יותר RAM למערכת תהליכים משאירים פחות זיכרון למשחק. המערכת משביתה את המשחק לפני שהוא הורג תהליכים במערכת.
  • שימוש בזיכרון של אפליקציות מותקנות: בדיקת המשחק במכשירים שבהם יש הרבה האפליקציות שהותקנו. אפליקציות של רשתות חברתיות וצ'אט צריכות לפעול כל הזמן, והן משפיעות על נפח הזיכרון הפנוי.

אם אתם לא יכולים להתחייב לתקציב זיכרון שמרני, קחו פסק זמן גמיש יותר . אם המערכת נתקלת בבעיות של זיכרון נמוך, צריך להקטין את כמות הזיכרון שהמשחק משתמש בו. לדוגמה, להקצות טקסטורות ברזולוציה נמוכה יותר או לאחסן פחות תוכנות הצללה (shader) בתגובה ל-onTrimMemory(). הגישה הדינמית הזו לזיכרון ההקצאה דורשת יותר עבודה של המפתח, במיוחד בעיצוב המשחק שלב אחד.

נמנעים מהתעסקות במכשיר

זעזוע מתרחש כשהזיכרון הפנוי נמוך, אבל לא נמוך מספיק, כדי לסיים את המשחק. במצב הזה, kswapd דורש חזרה דפים שהמשחק עדיין צריך, כך מנסה לטעון מחדש את הדפים מהזיכרון. אין מספיק מקום, לכן הדפים ממשיכים להיות מוחלפים (החלפה רציפה). מעקב המערכת מדווח על המצב הזה כשרשור כאשר kswapd פועל ברצף.

אחד מהתסמינים של חנק הוא זמני מסגרות ארוכים - אולי שנייה או יותר. הקטנה את טביעת הרגל הפחמנית של המשחק כדי לפתור את המצב הזה.

שימוש בכלים הזמינים

ב-Android יש אוסף של כלים שעוזרים להבין איך המערכת שמנהל את הזיכרון.

מידע על זכרונות

הכלי הזה אוסף נתונים סטטיסטיים על הזיכרון כדי להראות כמה זיכרון PSS הוקצה ואילו קטגוריות הוא שימש.

להדפיס את הנתונים הסטטיסטיים של meminfo באחד מ- בדרכים הבאות:

  • משתמשים בפקודה adb shell dumpsys meminfo package-name.
  • שימוש בקריאה ל-MemoryInfo מ-Android Debug API.

הנתון הסטטיסטיים של PrivateDirty מראה את כמות ה-RAM בתהליך שלא ניתן להעביר לדיסק ושאי אפשר לשתף אותו בכל תהליך אחר. רוב הסכום הזה יהיה זמין המערכת כשהתהליך הזה מאבד.

נקודות מעקב של זיכרון

נקודות מעקב של הזיכרון עוקבות אחר הכמות זיכרון RSS שבו המשחק משתמש. חישוב השימוש בזיכרון ב-RSS הרבה יותר מהיר מאשר חישוב שימוש ב-PSS. מאחר שהחישוב מהיר יותר, ה-RSS מציג רמת פירוט גבוהה יותר שינויים בגודל הזיכרון לצורך מדידות מדויקות יותר של שימוש שיא בזיכרון. לכן קל יותר להבחין בנקודות שיא שעלולות לגרום לכך שהמשחק ייגמר זיכרון.

פרפטו ועקבות ארוכים

Perfetto היא חבילת כלים לאיסוף מידע על הביצועים והזיכרון במכשיר, ומוצגים בממשק משתמש מבוסס-אינטרנט. הוא תומך במעקבים ארוכים באופן שרירותי, כדי שתוכלו לראות איך ה-RSS משתנה לאורך זמן. תוכלו גם ליצור שאילתות SQL על הנתונים שהוא מפיק לעיבוד אופליין. הפעלת מעקבים ארוכים אפליקציית System Tracing. צריך לוודא הקטגוריה memory:Memory מופעלת למעקב.

ערימה (heapprofd)

heapprofd הוא כלי למעקב אחרי זיכרון זה חלק מ-Perfetto. הכלי הזה יכול לעזור לך לאתר דליפות זיכרון על ידי הצגת שבו הזיכרון הוקצה באמצעות malloc. אפשר להתחיל להשתמש ב-heapprofd ב-Python, ומאחר שלכלי יש תקורה נמוכה, הוא לא משפיע ביצועים כמו כלים אחרים כמו Malloc Debug.

דוח על באג

bugreport הוא כלי לרישום ביומן שמאפשר לבדוק אם המשחק קרס כי נגמר לו הזיכרון. הפלט של הכלי מפורט הרבה יותר מאשר השימוש Logcat. היא שימושית לניפוי באגים בזיכרון כי היא מראה אם המשחק שלכם קרס כי נגמר לו הזיכרון או אם הוא נהרג על ידי המערכת לניהול למידה (LMK).

מידע נוסף זמין במאמר הבא: תיעוד וקריאה של דוחות על באגים.