W systemie Android próg limitu pamięci dla Memory Limiter (Android 17+) i wartość odniesienia dla danych o pamięci w Konsoli Google Play to 'anonimowy RSS + przestrzeń wymiany'. Ta wartość reprezentuje poziom obciążenia pamięci fizycznej faktycznie zajmowanej przez proces i jest kluczowym parametrem, który należy monitorować, aby zapewnić stabilne działanie aplikacji.
Obecnie trudno jest zmierzyć wykorzystanie pamięci, które dokładnie odpowiada „anonimowemu RSS + przestrzeni wymiany”, zarówno w czasie działania, jak i statycznie w silniku Unity.
Aby rozwiązać ten problem, na tej stronie opisujemy, jak śledzić wartość „anonimowy RSS + przestrzeń wymiany” z dużą niezawodnością za pomocą przybliżenia przy użyciu narzędzia Unity Profiler, interfejsu ProfileRecorder API i narzędzia Unity Memory Profiler w środowisku silnika Unity.
Sprawdzanie wykorzystania pamięci w czasie działania
W Unity bezpośrednie mierzenie dokładnego wykorzystania pamięci „anonimowy RSS + przestrzeń wymiany” w systemie Android w czasie działania bez obciążenia może być trudne. Możesz jednak dokładnie oszacować tę wartość (z odchyleniem około 10%) za pomocą wbudowanych interfejsów API narzędzia Unity Profiler.
Metoda 1: użycie Profilera
Możesz oszacować całkowite wykorzystanie pamięci, sumując wartości zwracane przez te interfejsy API narzędzia Profiler:
using UnityEngine;
using UnityEngine.Profiling;
public class MemoryMonitor : MonoBehaviour
{
public long GetEstimatedMemoryUsageBytes()
{
long totalReserved = Profiler.GetTotalReservedMemoryLong();
long monoHeapSize = Profiler.GetMonoHeapSizeLong();
return totalReserved + monoHeapSize;
}
}
Metoda 2: użycie klasy ProfilerRecorder
Za pomocą narzędzia ProfilerRecorder możesz śledzić dane Total Reserved Memory i Gfx Reserved Memory:
W kompilacjach deweloperskich: oblicz wartość „Total Reserved Memory” - „Gfx Reserved Memory”.
W kompilacjach produkcyjnych: użyj bezpośrednio wartości „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;
}
}
Ograniczenie:
Alokacji pamięci, które omijają menedżera pamięci Unity (np. NativeMalloc(IntPtr size)), nie można śledzić za pomocą tych interfejsów API.
Te interfejsy API mogą nie być obsługiwane w zależności od wersji Unity.
Analizowanie podziału pamięci (analiza statyczna)
Jeśli w czasie działania wykryjesz wysokie wykorzystanie pamięci, musisz określić, gdzie jest ona zużywana. Analiza dystrybucji pamięci pozwala wyeliminować niepotrzebne alokacje i zmniejszyć ogólne wykorzystanie pamięci gry.
Unity Memory Profiler
Aby przeprowadzić szczegółową analizę pamięci i zoptymalizować grę, użyj pakietu Unity Memory Profiler. Aby znaleźć elementy odpowiadające wykorzystaniu „anonimowy RSS + przestrzeń wymiany” w systemie operacyjnym Android:
- Zrób migawkę za pomocą narzędzia Unity Memory Profiler.
- Otwórz migawkę i przejdź do sekcji All of Memory > Resident Memory on Device (Cała pamięć > Pamięć rezydentna na urządzeniu).
Oblicz sumę tych elementów:
- Untracked
- środowisko wykonawcze Androida
- Natywna
- Zarządzane
Rysunek 1. Opisy pamięci są przechowywane w pamięci rezydentnej.
Suma całkowita stanowi praktyczny zamiennik „anonimowy RSS + przestrzeń wymiany” w systemie operacyjnym Android i dostarcza przydatnych informacji do analizy pamięci gry.
Ograniczenie:
Przy dużym obciążeniu pamięci system operacyjny Android może skompresować lub przenieść aktywne strony pamięci do przestrzeni wymiany, aby zwolnić pamięć RAM. Ponieważ narzędzie Unity Memory Profiler nie może śledzić pamięci przeniesionej do przestrzeni wymiany, w scenariuszach dużego wykorzystania pamięci mogą wystąpić rozbieżności.
Te funkcje mogą być ograniczone w zależności od wersji Unity.
Przykładowe skrypty w języku C#
Przykłady monitorowania stanu i
rozmiaru pamięci procesów gry w czasie działania znajdziesz w skryptach AndroidAndroidProcessStats.cs i
GameMemoryMonitor.cs.
- Skrypt
AndroidProcessStatspokazuje, jak używać JNI (Java Native Interface) do łączenia się z interfejsami APIActivityManagerw systemie Android. Zawiera też funkcje do pobierania uruchomionych procesów, ich ważności i stanu na poziomie systemu operacyjnego. Zawiera też proste metody odczytywania statystyk pamięci bezpośrednio z systemu plików/procw systemie Linux. - Skrypt
GameMemoryMonitorpokazuje, jak połączyć te informacje w celu ciągłego monitorowania i debugowania, w tym jak odpytywać interfejsy API Androida w wątku w tle, aby zapobiec obciążeniu wydajności (ponieważ używanie JNI i odpytywanie informacji o pamięci może być kosztowne), oraz jak łączyć się ze zdarzeniami cyklu życia, takimi jakOnApplicationPause, aby śledzić zmiany pamięci, gdy aplikacja jest w tle lub wznawiana.
Aby używać tych narzędzi, dodaj oba skrypty do folderu Assets i dołącz skrypt GameMemoryMonitor do obiektu GameObject w scenie.
Dokładniejsza ocena
Aby sprawdzić dokładne wartości „anonimowy RSS + przestrzeń wymiany” w systemie operacyjnym Android, użyj narzędzia Perfetto. Umożliwia ono dokładne pomiary wykorzystania pamięci na poziomie systemu i dokładną analizę rozmiaru pamięci gry.