Bu sayfada, Android 12'de kullanıma sunulan çeşitli bellek muhasebesi iyileştirmeleri açıklanmaktadır.
sysfs'deki DMA-BUF istatistikleri
Android 11 ve Android 12'de debugfs, kullanıcı derlemelerinde bağlanamaz. Bu nedenle, DMA-BUF istatistikleri Android 12'deki /sys/kernel/dmabuf/buffers dizininde sysfs'ya eklendi.
| Yol | Açıklama |
|---|---|
/sys/kernel/dmabuf/buffers
|
/sys/kernel/dmabuf/buffers dizini, her DMA-BUF'un dahili durumunun anlık görüntüsünü içerir.
/sys/kernel/dmabuf/buffers/<inode_number>, benzersiz inode numarası <inode_number> olan DMA-BUF'un istatistiklerini içerir.
|
/sys/kernel/dmabuf/buffers/<inode_number>/exporter_name
|
Bu salt okunur dosya, DMA-BUF dışa aktarıcısının adını içerir. |
/sys/kernel/dmabuf/buffers/<inode_number>/size
|
Bu salt okunur dosya, DMA-BUF'un boyutunu bayt cinsinden belirtir. |
libdmabufinfo API, dışa aktarıcı başına ve arabellek başına istatistikleri göstermek için DMA-BUF sysfs istatistiklerini ayrıştırır.
DMA-BUF'ları dışa aktaran çekirdek sürücüleri, DMA-BUF oluşturmak için dma_buf_export() API'sini çağırmadan önce exp_name alanını struct dma_buf_export_info dışa aktarıcı adına doğru şekilde ayarlamalıdır. Bu, libdmabufinfo ve dmabuf_dump aracının, dışa aktarıcı başına istatistikler elde etmesi için gereklidir. Bu istatistikler daha sonra hata raporunda gösterilir.
dmabuf_dump aracı, bu bilgileri -b adlı yeni bir bağımsız değişkenle çıkış olarak verecek şekilde değiştirildi.
DMA-BUF yığınları çerçevesiyle ilgili istatistikler
GKI 2.0'daki ION, DMA-BUF yığın çerçevesi lehine kullanımdan kaldırılıyor. Bu çerçeve, yukarı akış Linux çekirdeğinin bir parçasıdır.
Android 11'de aşağıdaki genel ION istatistikleri izlenir:
- Her ION yığını tarafından dışa aktarılan DMA-BUFLARIN toplam boyutu
- Her ION yığını tarafından depolanan, önceden ayrılmış ancak kullanılmayan belleğin toplam boyutu
Android 11'de ION başına yığın istatistiklerini kullanıma sunmak için bir arayüz bulunmamaktadır.
Aşağıdaki tabloda, ION istatistik arayüzleri ile Android 12'de DMA-BUF yığın çerçevesini kullanan cihazlardaki karşılıkları karşılaştırılmaktadır.
| Android 11 veya Android 12'de ION desteğiyle kullanıma sunulan cihazlar | Android 12'de DMA-BUF yığınlarıyla kullanıma sunulan cihazlar | |
|---|---|---|
| Yığın başına ION istatistikleri | Yok | DMA-BUF sysfs istatistiklerinden ayrıştırılır. |
| Dışa aktarılan DMA-BUFs'nin toplam boyutu | /sys/kernel/ion/total_heap_size_kb
(ION dışa aktarıcıları olmayanlar tarafından dışa aktarılan DMA-BUFs'lerin boyutu dahil değildir) |
DMA-BUF sysfs istatistiklerinden ayrıştırıldı
(Dışa aktarılan tüm DMA-BUF'ların boyutunu içerir). |
| Yığınlar tarafından havuzda toplanan toplam bellek | /sys/kernel/ion/total_pool_size_kb |
/sys/kernel/dma_heap/total_pool_size_kb |
Kayıp RAM hesaplama doğruluğunu artırma
Daha önce kayıp RAM hesaplaması aşağıdaki şekilde yapılıyordu:
final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- kernelUsed - memInfo.getZramTotalSizeKb();
totalPss bileşeni, GPU bellek kullanımını (Memtrack HAL'nin getMemory() arayüzü tarafından döndürülen) içeriyordu. kernelUsed bileşeni, toplam DMA-BUF bellek kullanımını içeriyordu.
Ancak Android cihazlarda GPU belleği şunlardan oluşur:
- GPU sürücüsü tarafından fiziksel sayfa ayırıcı kullanılarak yapılan doğrudan ayırmalar
- GPU adres alanına eşlenen DMA-BUFs
Bu nedenle, GPU adres alanına bellek eşlemesi yapılan DMA-BUF'lar, kayıp RAM hesaplanırken iki kez çıkarılıyordu. Android 12, GPU adres alanına eşlenen DMA-BUF'ların boyutunu hesaplamak için bir çözüm uygular. Bu çözüm, Kayıp RAM hesaplamasında yalnızca bir kez dikkate alındığı anlamına gelir.
Çözümün ayrıntıları aşağıdaki gibidir:
- PID 0 ile çağrıldığında Memtrack HAL API
getMemory(),MemtrackType::GLveMemtrackRecord::FLAG_SMAPS_UNACCOUNTEDiçin genel toplam GPU özel belleğini bildirmelidir. GLdışında birMemtrackTypeiçinPID 0ile çağrıldığındagetMemory()başarısız olmamalıdır. Bunun yerine 0 döndürmelidir.- Android 12'de eklenen GPU bellek izleme noktası/eBPF çözümü, toplam GPU belleğini hesaba katar. Toplam GPU belleğinden toplam GPU özel belleğini çıkardığınızda, GPU adres alanına eşlenen DMA-BUF'ların boyutu elde edilir. Bu değer daha sonra GPU bellek kullanımını doğru şekilde hesaba katarak Kayıp RAM hesaplamalarının doğruluğunu artırmak için kullanılabilir.
- Özel GPU belleği, çoğu Memtrack HAL uygulamasında
totalPss'ya dahil edilir. Bu nedenle,lostRAM'dan kaldırılmadan önce tekilleştirilmesi gerekir.
Uygulanan çözüm, bir sonraki bölümde ayrıntılı olarak açıklanmıştır.
Kayıp RAM'den Memtrack değişkenliğini kaldırma
Memtrack HAL uygulamaları iş ortakları arasında farklılık gösterebileceğinden, HAL'den totalPSS içinde yer alan GPU belleği her zaman tutarlı değildir. lostRAM değerindeki değişkenliği kaldırmak için MemtrackType::GRAPHICS ve MemtrackType::GL değerlerinde hesaba katılan bellek, lostRAM hesaplaması sırasında totalPss değerinden kaldırılır.
MemtrackType::GRAPHICS belleği totalPss'den kaldırılır ve aşağıdaki kodda gösterildiği gibi lostRAM hesaplamasındaki totalExportedDmabuf belleğiyle değiştirilir:
ActivityManagerService.java
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;
MemtrackType::GL belleği, totalPss'den kaldırılır ve aşağıdaki kodda gösterildiği gibi ActivityManagerService.java'daki lostRAM hesaplamasında özel GPU belleği (gpuPrivateUsage) ile değiştirilir:
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;
Kayıp RAM hesaplaması güncellendi
Hem toplam özel GPU belleği hem de toplam dışa aktarılan DMA arabellek belleği, lostRAM'den çıkarılan kernelUsed + totalPss içinde yer alır. Bu, hem çift sayımı hem de kayıp RAM hesaplamasından kaynaklanan Memtrack değişkenliğini ortadan kaldırır.
final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- kernelUsed - memInfo.getZramTotalSizeKb();
Doğrulama
VTS testleri, Android 12'de Linux çekirdek sürümü 5.4 veya daha yüksek bir sürümle kullanıma sunulan cihazların getGpuDeviceInfo() API'sini desteklemesi kuralını zorunlu kılar.
Yeni Memtrack HAL API getGpuDeviceInfo(), kullanılmakta olan GPU cihazıyla ilgili bilgileri döndürmelidir.
Bu sayede daha iyi bellek muhasebesi ve DMA arabelleği ile GPU bellek kullanımı hakkında daha iyi görünürlük sağlanır. Kayıp RAM ve bellek muhasebesini daha iyi yapmak için memtrack AIDL HAL'yi uygulayın. Bu özellik Google hizmetlerine bağlı değildir.
Uygulama
Bu özellik, AIDL Memtrack HAL'ye bağlıdır ve Android 12'de uygulanmasıyla ilgili talimatlar kodda yorum olarak yer alır. Gelecekteki sürümlerde tüm HIDL HAL'lerin AIDL'ye dönüştürülmesi planlanmaktadır.
Aşağıdaki API'ler core/java/android/os/Debug.java'ye eklendi:
/**
* 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();
Sürümünüzün amaçlandığı gibi çalıştığını doğrulamak için izleme noktalarını GPU sürücülerinizle entegre edin ve getMemory() ile MemtrackRecord::FLAG_SMAPS_UNACCOUNTED için PID 0 ile çağrıldığında genel toplam GPU özel belleğini doğru şekilde döndürmek üzere AIDL memtrack HAL getMemory() API'sini uygulayın.MemtrackType::GL