Bu sayfada, Android 12'de kullanıma sunulan çeşitli bellek hesabı iyileştirmeleri açıklanmaktadır.
sysfs'teki DMA-BUF istatistikleri
Android 11 ve Android 12'de debugfs
, kullanıcı derlemelerine eklenemez. Bu nedenle, DMA-BUF istatistikleri Android 12'deki /sys/kernel/dmabuf/buffers
dizininde sysfs
dosyasına 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> , <inode_number> benzersiz inode numarasına sahip DMA-BUF 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'nin boyutunu bayt cinsinden belirtir. |
libdmabufinfo
API, dışa aktaran ve arabellek başına istatistikleri ortaya çıkarmak için DMA-BUF sysfs
istatistiklerini ayrıştırır.
DMA-BUF'leri dışa aktaran çekirdek sürücülerinin, DMA-BUF oluşturmak için dma_buf_export()
API'yi çağırmadan önce struct dma_buf_export_info
öğesinin exp_name
alanını dışa aktaran adıyla doğru şekilde ayarlaması gerektiğini lütfen unutmayın.
Bu, libdmabufinfo
ve dmabuf_dump
aracının dışa aktaran başına istatistikleri türetmesi için gereklidir. Bu istatistikler daha sonra hata raporunda gösterilir.
dmabuf_dump aracı, bu bilgileri yeni bir bağımsız değişkenle (-b
) döndürecek şekilde değiştirildi.
DMA-BUF yığın çerçevesiyle ilgili istatistikler
GKI 2.0'daki ION desteği, yukarı akış Linux çekirdeğinin bir parçası olan DMA-BUF yığın çerçevesinin tercih edilmesi amacıyla kullanımdan kaldırılıyor.
Android 11'de aşağıdaki küresel ION istatistikleri izlenir:
- Her ION yığını tarafından dışa aktarılan DMA-BUF'lerin toplam boyutu
- Her ION yığını tarafından depolanan kullanılmayan önceden ayrılmış belleğin toplam boyutu
Android 11'de ION başına yığın istatistiklerini gösterecek bir arayüz yoktur.
Aşağıdaki tabloda, ION istatistik arayüzleri Android 12'de DMA-BUF yığın çerçevesini kullanan cihazlardaki benzerleriyle 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 başlatılan cihazlar | |
---|---|---|
Her yığın için ION istatistikleri | Yok | DMA-BUF sysfs istatistiklerinden ayrıştırılır. |
Dışa aktarılan DMA-BUF'ların toplam boyutu | /sys/kernel/ion/total_heap_size_kb
(ION olmayan dışa aktarıcılar tarafından dışa aktarılan DMA-BUF'lerin boyutunu içermez) |
DMA-BUF sysfs istatistiklerinden ayrıştırılır
(dışa aktarılan tüm DMA-BUF'ların boyutunu içerir). |
Yığınlar tarafından toplanan toplam bellek | /sys/kernel/ion/total_pool_size_kb |
/sys/kernel/dma_heap/total_pool_size_kb |
Kaybedilen RAM hesaplama doğruluğunu iyileştir
Daha önce, kaybedilen 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ı içeriyordu (Memtrack HAL'in getMemory() arayüzü tarafından döndürülür). kernelUsed
bileşeni, toplam DMA-BUF bellek kullanımını içeriyordu.
Ancak, Android cihazlarda GPU belleği aşağıdakilerden hangileridir:
- Fiziksel sayfa ayırıcı kullanarak GPU sürücüsü tarafından yapılan doğrudan ayırmalar
- GPU adres alanına eşlenen DMA-BUF'ler
Bu nedenle, GPU adres alanına bellek eşlenen DMA-BUF'ler, kaybedilen RAM hesaplanırken iki kez çıkarılıyordu. Android 12, GPU adres alanına eşlenen DMA-BUF'lerin boyutunu hesaplamak için bir çözüm uygular. Bu da, 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:
- Memtrack HAL API
getMemory()
, PID 0 ile çağrıldığında MemtrackType::GL ve MemtrackRecord::FLAG_SMAPS_UNACCOUNTED için genel toplam GPU özel belleği bildirmelidir. GL
dışında birMemtrackType
içinPID
0
ile çağrılan getMemory() 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 özel belleğinin toplam GPU belleğinden çıkarılması, GPU adres alanına eşlenen DMA-BUF'lerin boyutunu sağlar. Bu değer daha sonra GPU bellek kullanımını doğru şekilde hesaba katarak Kaybedilen RAM hesaplamalarının doğruluğunu iyileştirmek için kullanılabilir.
- Özel GPU belleği, çoğu Memtrack HAL uygulamasında
totalPss
içinde yer alır ve bu nedenlelostRAM
ürününden kaldırılmadan önce tekilleştirilmesi gerekir.
Uygulanan çözüm bir sonraki bölümde ayrıntılı olarak açıklanmıştır.
Kaybedilen RAM'den Memtrack değişkenliğini kaldır
Memtrack HAL uygulamaları iş ortakları arasında farklılık gösterebileceğinden, HAL'deki totalPSS
özelliğine dahil edilen GPU belleği her zaman tutarlı değildir. lostRAM
'teki değişkenliği kaldırmak için lostRAM
hesaplaması sırasında MemtrackType::GRAPHICS
ve MemtrackType::GL
'de hesaba katılan bellek totalPss
'ten kaldırılır.
MemtrackType::GRAPHICS
belleği totalPss
'dan kaldırılır ve aşağıdaki gibi ActivityManagerService.java'daki lostRAM
hesaplamasında totalExportedDmabuf
belleğiyle değiştirilir:
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
'dan kaldırılır ve ActivityManagerService.java'daki lostRAM
hesaplamasında aşağıdaki gibi ö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 dışa aktarılan toplam DMA arabellek belleği, lostRAM
öğesinden kaldırılan kernelUsed + totalPss
içinde yer alır. Bu, kaybedilen RAM hesaplamasında hem çift sayımı hem de 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 sonraki bir sürümle başlatılan cihazların getGpuDeviceInfo() API'yi desteklediği kuralını uygular.
Yeni Memtrack HAL API getGpuDeviceInfo()
, kullanılan GPU cihazı hakkında bilgi döndürmelidir.
Bu sayede DMA arabelleği ve GPU bellek kullanımıyla ilgili daha iyi bir bellek hesabı ve görünürlük elde edilir. Daha iyi kaybedilen RAM ve bellek hesaplama için memtrack AIDL HAL'yi uygulayın. Bu özellik Google hizmetlerine bağlı değildir.
Uygulama
Bu özellik AIDL Memtrack HAL'a bağlıdır ve Android 12'de uygulamaya ilişkin talimatlar koda yorum olarak eklenmiştir.
Tüm HIDL HAL'lerin gelecekteki sürümlerde AIDL'ye dönüştürülmesi planlanmaktadır.
Aşağıdaki API'ler core/java/android/os/Debug.java
'e 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ığı şekilde çalıştığından emin olmak için izleme noktalarını GPU sürücülerinize entegre edin ve MemtrackType::GL ve MemtrackRecord::FLAG_SMAPS_UNACCOUNTED için PID 0 ile çağrıldığında global toplam GPU özel belleğini doğru şekilde döndürmek üzere AIDL memtrack HAL getMemory()
API'sini uygulayın.