במערכת Android, סף מגבלת הזיכרון של Memory Limiter (Android 17 ואילך) וערך ההשוואה של נתוני תפקוד האפליקציה שקשורים לזיכרון ב-Google Play Console הוא anonymous RSS + swap. הערך הזה מייצג את רמת העומס בזיכרון הפיזי שתהליך מסוים תופס בפועל, והוא מדד קריטי שצריך לעקוב אחריו כדי להבטיח פעולה יציבה של האפליקציה.
בשלב הזה, קשה למדוד את השימוש בזיכרון שתואם בדיוק ל-'anonymous RSS + swap' בזמן הריצה או באופן סטטי בתוך Unity Engine.
כדי לפתור את הבעיה הזו, בדף הזה מוסבר איך לעקוב אחרי הערך anonymous RSS + swap ברמת מהימנות גבוהה באמצעות קירוב בעזרת Unity Profiler, ProfileRecorder API ו-Unity Memory Profiler בסביבת Unity Engine.
בדיקת השימוש בזיכרון בזמן הריצה
ב-Unity, קשה למדוד ישירות את השימוש בזיכרון של Android 'anonymous RSS + swap' בזמן הריצה בלי תקורה. עם זאת, אפשר להעריך את הערך הזה (בטווח של 10% שונות) באמצעות ממשקי ה-API המובנים של Unity Profiler.
שיטה 1: שימוש בProfiler
כדי להעריך את השימוש הכולל בזיכרון, אפשר לסכם את הערכים שמוחזרים על ידי ממשקי ה-API הבאים של Profiler:
using UnityEngine;
using UnityEngine.Profiling;
public class MemoryMonitor : MonoBehaviour
{
public long GetEstimatedMemoryUsageBytes()
{
long totalReserved = Profiler.GetTotalReservedMemoryLong();
long monoHeapSize = Profiler.GetMonoHeapSizeLong();
return totalReserved + monoHeapSize;
}
}
שיטה 2: שימוש במחלקה ProfilerRecorder
אפשר לעקוב אחרי המדדים Total Reserved Memory ו-Gfx Reserved Memory באמצעות ProfilerRecorder:
בגרסאות פיתוח: מחשבים את הערך של 'Total Reserved Memory' (הזיכרון הכולל ששמור) פחות הערך של 'Gfx Reserved Memory' (הזיכרון ששמור ל-Gfx).
בגרסאות Release: משתמשים ישירות ב-Total Reserved Memory.
using Unity.Profiling;
using UnityEngine;
public class MemoryMonitor : MonoBehaviour
{
ProfilerRecorder totalRecorder;
#if DEVELOPMENT_BUILD
ProfilerRecorder gfxRecorder;
#endif
private void OnEnable()
{
totalRecorder = ProfilerRecorder.StartNew(ProfilerCategory.Memory, "Total Reserved Memory");
#if DEVELOPMENT_BUILD
gfxRecorder = ProfilerRecorder.StartNew(ProfilerCategory.Memory, "Gfx Reserved Memory");
#endif
}
private void OnDisable()
{
totalRecorder.Dispose();
#if DEVELOPMENT_BUILD
gfxRecorder.Dispose();
#endif
}
public long GetEstimatedMemoryUsageBytes()
{
#if DEVELOPMENT_BUILD
if (totalRecorder.Valid && gfxRecorder.Valid)
{
return totalRecorder.LastValue - gfxRecorder.LastValue;
}
#else
if (totalRecorder.Valid)
{
return totalRecorder.LastValue;
}
#endif
return 0;
}
}
מגבלה:
אי אפשר לעקוב אחרי הקצאות זיכרון שעוקפות את מנהל הזיכרון של Unity (למשל, NativeMalloc(IntPtr size)) באמצעות ממשקי ה-API האלה.
יכול להיות שממשקי ה-API האלה לא נתמכים, בהתאם לגרסת Unity שלכם.
ניתוח של פירוט הזיכרון (ניתוח סטטי)
אם מזוהה שימוש גבוה בזיכרון בזמן הריצה, צריך לזהות איפה הזיכרון נצרך. ניתוח של חלוקת הזיכרון מאפשר לכם לבטל הקצאות מיותרות ולצמצם את הזיכרון שבשימוש הכולל של המשחק.
Unity Memory Profiler
כדי לבצע ניתוח מעמיק של הזיכרון ולבצע אופטימיזציה של המשחק, אפשר להשתמש בחבילה Unity Memory Profiler. כדי לאתר את הפריטים שמתאימים לשימוש ב-Android OS anonymous RSS + swap:
- יצירת תמונת מצב באמצעות הכלי Unity Memory Profiler.
- פותחים את התמונה של מצב המערכת ועוברים אל All of Memory > Resident Memory on Device (כל הזיכרון > זיכרון תושב במכשיר).
חשבו את הסכום של הפריטים הבאים:
- לא נכלל במעקב
- סביבת זמן ריצה ל-Android (ART)
- פורמט מותאם
- מנוהל
איור 1. תיאורי הזיכרון מאוחסנים בזיכרון התושב
הסכום הכולל משמש כתחליף מעשי ל-anonymous RSS + swap במערכת ההפעלה Android, ומספק תובנות פרקטיות לניתוח הזיכרון של המשחק.
מגבלה:
במצבים של עומס כבד על הזיכרון, מערכת ההפעלה Android עשויה לדחוס או להחליף דפי זיכרון פעילים כדי לפנות זיכרון RAM. מכיוון ש-Unity Memory Profiler לא יכול לעקוב אחרי זיכרון שהועבר, יכול להיות שיהיו אי-התאמות בתרחישים של שימוש בזיכרון גבוה.
יכול להיות שהתכונות האלה יהיו מוגבלות בהתאם לגרסת Unity שלכם.
הערכה מדויקת יותר
כדי לאמת את הערכים המדויקים של מערכת ההפעלה Android anonymous RSS + swap, צריך להשתמש ב-Perfetto. הכלי מאפשר לכם למדוד את השימוש המדויק בזיכרון ברמת המערכת ולנתח ביסודיות את הזיכרון שבשימוש של המשחק.