Bu sayfada, Android 12'de kullanıma sunulan çeşitli bellek hesabı iyileştirmeleri açıklanmaktadır.
Syfs'te DMA-BUF istatistikleri
Android 11 ve Android 12'de debugfs
,
kullanıcı derlemelerine eklenir. DMA-BUF istatistikleri, sysfs
Android 12'de /sys/kernel/dmabuf/buffers
dizini.
Yol | Açıklama |
---|---|
/sys/kernel/dmabuf/buffers
|
/sys/kernel/dmabuf/buffers dizini, şu öğenin anlık görüntüsünü içerir:
dahili durumu hakkında daha fazla bilgi edinin.
/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 aktarıcı ve arabellek başına istatistikleri göstermek için DMA-BUF sysfs
istatistiklerini ayrıştırır.
DMA-BUF'leri dışa aktaran çekirdek sürücülerinin exp_name
struct dma_buf_export_info
alanını doğru şekilde dışa aktarmadan önce
dma_buf_export()
API'yi çağırarak DMA-BUF'yi oluşturun.
Bu, libdmabufinfo
ve dmabuf_dump
aracının dışa aktarıcı başına istatistikler oluşturması için gereklidir. Bu istatistikler daha sonra bugreport'ta 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 sonlandırılıyor. Bunun yerine DMA-BUF yığın çerçevesi kullanılacaktır. Bu kod, yukarı akış Linux çekirdeğinin bir parçasıdır.
Aşağıdaki küresel ION istatistikleri Android 11'de izlenir:
- Her ION yığını tarafından dışa aktarılan DMA-BUF'ların toplam boyutu
- Her ION yığını tarafından depolanan, kullanılmayan, önceden ayrılmış belleğin toplam boyutu
Android 11'de ION yığın başına istatistikleri göstermek için kullanılabilecek bir arayüz yoktur.
Aşağıdaki tabloda ION istatistik arayüzleri ile bunların eşdeğerleri vardı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 |
Kayıp RAM hesaplama doğruluğunu iyileştirme
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() işlevi
arayüz). kernelUsed
bileşeni, toplam DMA-BUF bellek kullanımını içeriyordu.
Ancak Android cihazlarda GPU belleği aşağıdaki kaynaklardan alınmıştır:
- Fiziksel sayfa ayırıcıyı kullanarak GPU sürücüsü tarafından yapılan doğrudan ayırmalar
- GPU adres alanına eşlenen DMA-BUF'lar
Bu nedenle, GPU adres alanına bellek eşlenen DMA-BUF'ler değeri iki kez çıkarılmıştır. Android 12 GPU'ya eşlenen DMA-BUF'lerin boyutunu hesaplamak için bir çözüm uygular yani Kayıp URL'sinde yalnızca bir kez RAM hesaplaması.
Çözümün ayrıntıları aşağıdaki gibidir:
- Memtrack HAL API'si
getMemory()
PID 0 ile çağrıldığında, yalnızca MemtrackType::GL ve MemtrackRecord::FLAG_SMAPS_UNACCOUNTED. GL
dışında birMemtrackType
içinPID
0
ile çağrılan getMemory() başarısız olmamalıdır. Bunun yerine 0 değerini döndürmelidir.- Android 12'de eklenen GPU bellek izleme noktası/eBPF çözümü, toplam GPU belleğini hesaba katar. Toplam GPU özel belleği toplam GPU belleğinden çıkarılarak 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 iyileştirmek için kullanılabilir.
- Özel GPU belleği, çoğu Memtrack HAL uygulamasında
totalPss
'e dahil edildiğindenlostRAM
'ten kaldırılmadan önce tekilleştirilmelidir.
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ına göre değişiklik gösterebileceğinden GPU belleği
HAL'den totalPSS
özelliğine dahil edilenler 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
anı totalPss
cihazından kaldırıldı ve
lostRAM
hesaplamasında özel GPU belleği (gpuPrivateUsage
)
ActivityManagerService.java
aşağıdaki gibidir:
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
kernelUsed + totalPss
içinde yer alır ve lostRAM
öğesinden kaldırılır. Bu sayede, kayıp RAM hesaplamasında hem çift sayma hem de Memtrack değişkenliği ortadan kaldırılır.
final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- kernelUsed - memInfo.getZramTotalSizeKb();
Doğrulama
VTS testleri, Android 12'de 5.4 veya daha yeni bir Linux çekirdeği sürümüyle kullanıma sunulan cihazların getGpuDeviceInfo() API'sini desteklemesi kuralını zorunlu kılar.
Yeni bir Memtrack HAL API'si getGpuDeviceInfo()
, kullanılan GPU cihazıyla ilgili bilgileri döndürmelidir.
Bu, daha iyi bellek hesaplama ve DMA arabelleği ve GPU için görünürlük sağlar bellek kullanımından kaynaklanır. Kaybedilen RAM ve bellek hesaplarının daha iyi olması için memtrack AIDL HAL'i uygulayın. Bu özellik Google hizmetlerine bağlı değildir.
Uygulama
Bu özellik, AIDL Memtrack HAL'e bağlıdır ve Android 12'de uygulama talimatları koda yorum olarak eklenmiştir.
Tüm HIDL HAL'lerin gelecekteki sürümlerde AIDL'ye dönüştürülmesi planlanmaktadır.
core/java/android/os/Debug.java
ürününe aşağıdaki API'ler 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 gerektiği gibi çalıştığından emin olmak için izleme noktalarını GPU'nuza entegre edin
ve AIDL memtrack HAL getMemory()
API'yi uygulayarak
MemtrackType::GL için PID 0 ile çağrıldığında genel toplam GPU ile özel bellek
ve MemtrackRecord::FLAG_SMAPS_UNACCOUNTED.