Na tej stronie opisujemy różne ulepszenia w zakresie zliczania pamięci wprowadzone w Androidzie 12.
Statystyki DMA-BUF w sysfs
W Androidzie 11 i 12 nie można zamontować debugfs
w kompilacji użytkownika. W Androidzie 12 statystyki DMA-BUF zostały dodane do sysfs
w katalogu /sys/kernel/dmabuf/buffers
.
Ścieżka | Opis |
---|---|
/sys/kernel/dmabuf/buffers
|
Katalog /sys/kernel/dmabuf/buffers zawiera migawkę stanu wewnętrznego każdego obiektu DMA-BUF.
/sys/kernel/dmabuf/buffers/<inode_number> zawiera statystyki dla DMA-BUF z unikalnym numerem i-węzłów: <inode_number> .
|
/sys/kernel/dmabuf/buffers/<inode_number>/exporter_name
|
Ten plik tylko do odczytu zawiera nazwę eksportera DMA-BUF. |
/sys/kernel/dmabuf/buffers/<inode_number>/size
|
Ten plik tylko do odczytu określa rozmiar DMA-BUF w bajtach. |
Interfejs API libdmabufinfo
analizuje statystyki DMA-BUF sysfs
, aby wyświetlić statystyki dotyczące eksportera i bufora.
Pamiętaj, że sterowniki jądra, które eksportują obiekty DMA-BUF, muszą prawidłowo ustawić w polu exp_name
struct dma_buf_export_info
nazwę eksportera przed wywołaniem interfejsu API dma_buf_export()
w celu utworzenia DMA-BUF.
Jest to wymagane przez libdmabufinfo
i narzędzie dmabuf_dump
do generowania statystyk na temat poszczególnych eksporterów, które są następnie widoczne w raporcie o błędzie.
Narzędzie dmabuf_dump zostało zmodyfikowane, aby wyświetlać te informacje za pomocą nowego argumentu -b
.
Statystyki platformy DMA-BUF
Procesor ION w GKI 2.0 jest wycofywany i zastępuje platformę stosu DMA-BUF, która jest częścią nadrzędnego jądra systemu Linux.
W Androidzie 11 śledzone są te globalne statystyki ION:
- Łączny rozmiar buforów DMA-BUF eksportowanych przez każdą stertę ION
- Łączny rozmiar nieużywanej wstępnie przydzielonej pamięci przechowywanej przez każdą stertę ION
W Androidzie 11 nie ma interfejsu umożliwiającego wyświetlanie statystyk dotyczącej poszczególnych stosów ION.
W poniższej tabeli porównano interfejsy statystyk ION z ich odpowiednikami w przypadku urządzeń korzystających z platformy sterty DMA-BUF w Androidzie 12.
Android 11 lub urządzenia z obsługą ION w Androidzie 12 | Urządzenia uruchamiane z użyciem stosu DMA-BUF w Androidzie 12 | |
---|---|---|
Statystyki ION na stertę | Brak | Przetworzone z statystyk sysfs DMA-BUF |
Łączny rozmiar wyeksportowanych buforów DMA-BUF | /sys/kernel/ion/total_heap_size_kb
(Nie uwzględnia rozmiaru plików DMA-BUF wyeksportowanych przez narzędzia do eksportu inne niż ION) |
Przeanalizowano ze statystyk sysfs DMA-BUF
(obejmuje rozmiar wszystkich wyeksportowanych plików DMA-BUF). |
Łączna ilość pamięci w puli stertów | /sys/kernel/ion/total_pool_size_kb |
/sys/kernel/dma_heap/total_pool_size_kb |
Poprawić dokładność obliczania utraconej pamięci RAM
Wcześniej utrata pamięci RAM była obliczana w ten sposób:
końcowy długi czas lostRAM
= memInfo.getTotalSizeKb(
) – (totalPss
– totalSwapPss
)
– memInfo.getFreeSizeKb()
– memInfo.getCachedSizeKb()
– kernelUsed
– memInfo.getZramTotalSizeKb()
;
Komponent totalPss
uwzględniał wykorzystanie pamięci GPU (zwracane przez interfejs getMemory() interfejsu Memtrack HAL). Komponent kernelUsed
obejmuje łączne wykorzystanie pamięci DMA-BUF.
W przypadku urządzeń z Androidem pamięć GPU pochodzi z:
- bezpośrednie przydzielenia dokonane przez sterownik GPU za pomocą przydzielacza stron fizycznych;
- Obiekty DMA-BUF zmapowane na przestrzeń adresową GPU
W związku z tym podczas obliczania utraty pamięci RAM obiekty DMA-BUF zmapowane na przestrzeń adresową GPU były odejmowane dwukrotnie. Android 12 wdraża rozwiązanie służące do obliczania rozmiaru plików DMA-BUF zmapowanych na przestrzeń adresową GPU, co oznacza, że w ramach obliczania utraconej pamięci RAM są one uwzględniane tylko raz.
Szczegóły rozwiązania:
- Interfejs API Memtrack HAL
getMemory()
wywoływany z PID 0 musi przekazywać globalną łączną pamięć prywatną GPU w przypadku MemtrackType::GL i MemtrackRecord::FLAG_SMAPS_UNACCOUNTED. - Metoda getMemory() w przypadku wywołania funkcji
PID
0
w przypadku funkcjiMemtrackType
innej niżGL
nie może kończyć się niepowodzeniem. Zamiast tego musi zwracać wartość 0. - Rozwiązanie punktu śledzenia pamięci GPU/eBPF dodane w Androidzie 12 uwzględnia łączną pamięć GPU. Odejmując łączną ilość prywatnej pamięci GPU od łącznej pamięci GPU, uzyskujesz rozmiar DMA-BUF zmapowanych na przestrzeń adresową GPU. Wartość ta może być następnie używana do zwiększania dokładności obliczeń utraconej pamięci RAM przez prawidłowe uwzględnienie wykorzystania pamięci GPU.
- W większości implementacji HAL Memtrack prywatna pamięć GPU jest uwzględniona w
totalPss
, dlatego przed usunięciem zlostRAM
należy ją usunąć.
Szczegóły wdrożonego rozwiązania znajdziesz w następnej sekcji.
Usuń zmienność Memtrack z utraconej pamięci RAM
Implementacje HAL Memtrack mogą się różnić w zależności od partnera, dlatego pamięć GPU uwzględniona w wartości totalPSS
w HAL nie zawsze jest spójna. Aby można było usunąć zmienność z wartości lostRAM
, podczas obliczania lostRAM
z totalPss
zostanie usunięta pamięć uwzględniona w parametrach MemtrackType::GRAPHICS
i MemtrackType::GL
.
Pamięć MemtrackType::GRAPHICS
jest usuwana z totalPss
i zastępowana pamięcią totalExportedDmabuf
w obliczeniach lostRAM
w ActivityManagerService.java , jak pokazano poniżej:
final long totalExportedDmabuf = Debug.getDmabufTotalExportedKb();
. . .
final long dmabufUnmapped = totalExportedDmabuf - dmabufMapped;
. . .
// Account unmapped dmabufs as part of the kernel memory allocations
kernelUsed += dmabufUnmapped;
// Replace Memtrack HAL reported Graphics category with mapped dmabufs
totalPss -= totalMemtrackGraphics;
totalPss += dmabufMapped;
Pamięć MemtrackType::GL
jest usuwana z totalPss
i zastępowana prywatną pamięcią GPU (gpuPrivateUsage
) w obliczeniach lostRAM
w ActivityManagerService.java , jak pokazano poniżej:
final long gpuUsage = Debug.getGpuTotalUsageKb();
. . .
final long gpuPrivateUsage = Debug.getGpuPrivateMemoryKb();
. . .
// Replace the Memtrack HAL-reported GL category with private GPU allocations.
// Count it as part of the kernel memory allocations.
totalPss -= totalMemtrackGl;
kernelUsed += gpuPrivateUsage;
Zaktualizowano obliczanie utraconej pamięci RAM
Zarówno łączna prywatna pamięć GPU, jak i łączna wyeksportowana pamięć bufora DMA znajdują się w kernelUsed + totalPss
, która jest usuwana z lostRAM
. Pozwala to wyeliminować zarówno podwójne zliczanie, jak i zmienność w ramach Memtracka z utraty pamięci RAM.
final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- kernelUsed - memInfo.getZramTotalSizeKb();
Weryfikacja
Testy VTS egzekwują zasadę, że urządzenia uruchamiane w Androidzie 12 z jądrem Linuksa w wersji 5.4 lub nowszej obsługują interfejs API getGpuDeviceInfo().
Nowy interfejs Memtrack HAL API getGpuDeviceInfo()
musi zwracać informacje o używanym urządzeniu GPU.
Zapewnia to lepszy podgląd i kontrolę wykorzystania pamięci DMA oraz pamięci GPU. Zaimplementuj memtrack HAL AIDL, aby lepiej zmniejszyć utraconą pamięć RAM i obliczać ilość pamięci. Ta funkcja nie zależy od usług Google.
Implementacja
Ta funkcja zależy od interfejsu AIDL Memtrack HAL, a wskazówki dotyczące jego implementacji w Androidzie 12 są zawarte w kodzie jako komentarze.
W przyszłych wersjach wszystkie interfejsy HIDL HAL zostaną przekształcone w interfejsy AIDL.
Do usługi core/java/android/os/Debug.java
dodaliśmy te interfejsy API:
/**
* Return total memory size in kilobytes for exported DMA-BUFs or -1 if
* the DMA-BUF sysfs stats at /sys/kernel/dmabuf/buffers could not be read.
*
* @hide
*/
public static native long getDmabufTotalExportedKb();
/**
* Return memory size in kilobytes allocated for DMA-BUF heap pools or -1 if
* /sys/kernel/dma_heap/total_pools_kb could not be read.
*
* @hide
*/
public static native long getDmabufHeapPoolsSizeKb();
Aby mieć pewność, że wersja działa zgodnie z oczekiwaniami, zintegruj punkty śledzenia w sterownikach GPU i zaimplementuj interfejs API AIDL memtrack HAL getMemory()
, aby poprawnie zwracać globalną łączną pamięć GPU w przypadku wywołania z PID 0 dla funkcji MemtrackType::GL i MemtrackRecord::FLAG_SMAPS_UNACCOUNTED.