Na tej stronie opisano różne ulepszenia rozliczania pamięci wprowadzone w systemie Android 12.
Statystyki DMA-BUF w sysfs
W systemach Android 11 i Android 12 debugfs
nie można montować w kompilacjach użytkownika. Dlatego statystyki DMA-BUF zostały dodane do sysfs
w katalogu /sys/kernel/dmabuf/buffers
w systemie Android 12.
Ścieżka | Opis |
---|---|
/sys/kernel/dmabuf/buffers | Katalog /sys/kernel/dmabuf/buffers zawiera migawkę wewnętrznego stanu każdego DMA-BUF. /sys/kernel/dmabuf/buffers/<inode_number> zawiera statystyki dla DMA-BUF z unikalnym numerem i-węzła <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 sysfs
DMA-BUF, aby wyświetlić statystyki według eksportera i bufora.
Należy pamiętać, że sterowniki jądra, które eksportują DMA-BUF, muszą poprawnie ustawić pole exp_name
struct dma_buf_export_info
na nazwę eksportera przed wywołaniem funkcji API dma_buf_export()
w celu utworzenia DMA-BUF. Jest to wymagane, aby libdmabufinfo
i narzędzie dmabuf_dump
mogły uzyskać statystyki dotyczące poszczególnych eksporterów, które następnie są prezentowane w raporcie o błędach.
Narzędzie dmabuf_dump zostało zmodyfikowane tak, aby wyświetlać te informacje z nowym argumentem -b
.
Statystyki dla struktury stert DMA-BUF
ION w GKI 2.0 jest przestarzały na rzecz struktury stert DMA-BUF , która jest częścią jądra Linuksa.
W systemie Android 11 śledzone są następujące globalne statystyki ION:
- Całkowity rozmiar DMA-BUF eksportowanych przez każdą stertę ION
- Całkowity rozmiar niewykorzystanej, wstępnie przydzielonej pamięci przechowywanej przez każdą stertę ION
W systemie Android 11 nie jest dostępny interfejs umożliwiający wyświetlenie statystyk sterty na ION.
Poniższa tabela porównuje interfejsy statystyczne ION z ich odpowiednikami dla urządzeń korzystających ze struktury sterty DMA-BUF w systemie Android 12.
Android 11 lub Urządzenia uruchamiane z obsługą ION w Androidzie 12 | Urządzenia uruchamiane ze stertami DMA-BUF w systemie Android 12 | |
---|---|---|
Statystyki ION na stertę | Nic | Przeanalizowano na podstawie statystyk sysfs DMA-BUF |
Całkowity rozmiar wyeksportowanych plików DMA-BUF | /sys/kernel/ion/total_heap_size_kb (Nie obejmuje wielkości DMA-BUF eksportowanych przez eksporterów spoza ION) | Przeanalizowano na podstawie statystyk sysfs DMA-BUF (obejmuje rozmiar wszystkich eksportowanych DMA-BUF). |
Całkowita pamięć zgromadzona przez sterty | /sys/kernel/ion/total_pool_size_kb | /sys/kernel/dma_heap/total_pool_size_kb |
Popraw dokładność obliczeń utraconej pamięci RAM
Poprzednio obliczenia utraconej pamięci RAM wykonywano w następujący sposób:
końcowa długa lostRAM
= memInfo.getTotalSizeKb(
) - ( totalPss
- totalSwapPss
)
- memInfo.getFreeSizeKb()
- memInfo.getCachedSizeKb()
- kernelUsed
- memInfo.getZramTotalSizeKb()
;
Komponent totalPss
uwzględniał wykorzystanie pamięci GPU (zwracane przez interfejs getMemory() Memtrack HAL). Komponent kernelUsed
uwzględniał całkowite wykorzystanie pamięci DMA-BUF. Jednak w przypadku urządzeń z Androidem pamięć GPU pochodziła z następujących źródeł:
- Bezpośrednie alokacje dokonywane przez sterownik GPU przy użyciu fizycznego alokatora stron
- DMA-BUF mapowane na przestrzeń adresową GPU
Dlatego też DMA-BUF, które zostały zmapowane w pamięci w przestrzeni adresowej GPU, zostały odjęte dwukrotnie podczas obliczania utraconej pamięci RAM. W Androidzie 12 zaimplementowano rozwiązanie obliczające wielkość DMA-BUF mapowanych w przestrzeń adresową GPU, co oznacza, że jest ona uwzględniana tylko raz w kalkulacji utraconej pamięci RAM.
Szczegóły rozwiązania są następujące:
- Funkcja
getMemory()
API Memtrack HAL po wywołaniu z PID 0 musi raportować globalną całkowitą pamięć prywatną GPU dla MemtrackType::GL i MemtrackRecord::FLAG_SMAPS_UNACCOUNTED. - getMemory() wywołana z
PID
0
dlaMemtrackType
innego niżGL
nie może zakończyć się niepowodzeniem. Zamiast tego musi zwrócić 0. - Rozwiązanie Tracepoint/eBPF pamięci GPU dodane w systemie Android 12 uwzględnia całkowitą pamięć GPU. Odjęcie całkowitej pamięci prywatnej GPU od całkowitej pamięci GPU daje rozmiar DMA-BUF odwzorowanych w przestrzeni adresowej GPU. Wartości można następnie użyć do poprawy dokładności obliczeń utraconej pamięci RAM poprzez prawidłowe uwzględnienie wykorzystania pamięci GPU.
- Prywatna pamięć GPU jest zawarta w
totalPss
w większości implementacji Memtrack HAL i dlatego należy ją zdeduplikować przed usunięciem zlostRAM
.
Wdrożone rozwiązanie opisano szczegółowo w następnej sekcji.
Usuń zmienność Memtrack z utraconej pamięci RAM
Ponieważ implementacje Memtrack HAL mogą się różnić u poszczególnych partnerów, pamięć GPU zawarta w totalPSS
z HAL nie zawsze jest spójna. Aby usunąć zmienność z lostRAM
, pamięć uwzględniana w MemtrackType::GRAPHICS
i MemtrackType::GL
jest usuwana z totalPss
podczas obliczania lostRAM
.
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
) podczas obliczania 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 obliczenia utraconej pamięci RAM
Zarówno całkowita prywatna pamięć GPU, jak i całkowita wyeksportowana pamięć bufora DMA są zawarte w kernelUsed + totalPss
, które są usuwane z lostRAM
. Eliminuje to zarówno podwójne liczenie, jak i zmienność Memtrack wynikającą z obliczeń utraconej pamięci RAM.
final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- kernelUsed - memInfo.getZramTotalSizeKb();
Walidacja
Testy VTS egzekwują zasadę, że urządzenia uruchamiane w systemie Android 12 z jądrem Linux w wersji 5.4 lub wyższej obsługują API getGpuDeviceInfo() .
Nowe API Memtrack HAL getGpuDeviceInfo()
musi zwracać informacje o używanym urządzeniu GPU.
Zapewnia to lepsze rozliczanie pamięci i wgląd w wykorzystanie bufora DMA i pamięci GPU. Zaimplementuj memtrack AIDL HAL, aby uzyskać lepsze rozliczanie utraconej pamięci RAM i pamięci. Ta funkcja nie jest zależna od usług Google.
Realizacja
Ta funkcja zależy od AIDL Memtrack HAL , a wskazówki dotyczące jej implementacji w systemie Android 12 są zawarte w kodzie jako komentarze.
Planuje się, że w przyszłych wersjach wszystkie warstwy HIDL HAL zostaną przekonwertowane na AIDL.
Do core/java/android/os/Debug.java
dodano następujące 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 Twoja wersja działa zgodnie z oczekiwaniami, zintegruj punkty śledzenia ze sterownikami GPU i zaimplementuj API AIDL memtrack HAL getMemory()
, aby poprawnie zwrócić globalną całkowitą pamięć prywatną GPU po wywołaniu z PID 0 dla MemtrackType::GL i MemtrackRecord:: FLAG_SMAPS_UNACCOUNTED.