Halaman ini menjelaskan berbagai peningkatan akuntansi memori yang diperkenalkan di Android 12.
Statistik DMA-BUF di sysfs
Di Android 11 dan Android 12, debugfs
tidak dapat dipasang di build Pengguna. Jadi statistik DMA-BUF telah ditambahkan ke sysfs
di direktori /sys/kernel/dmabuf/buffers
di Android 12.
Jalur | Keterangan |
---|---|
/sys/kernel/dmabuf/buffers | Direktori /sys/kernel/dmabuf/buffers berisi cuplikan status internal setiap DMA-BUF. /sys/kernel/dmabuf/buffers/<inode_number> berisi statistik untuk DMA-BUF dengan nomor inode unik <inode_number> . |
/sys/kernel/dmabuf/buffers/<inode_number>/exporter_name | File read-only ini berisi nama eksportir DMA-BUF. |
/sys/kernel/dmabuf/buffers/<inode_number>/size | File read-only ini menentukan ukuran DMA-BUF dalam byte. |
API libdmabufinfo
mengurai statistik sysfs
DMA-BUF untuk mengekspos statistik per eksportir dan per buffer.
Perlu diingat bahwa driver kernel yang mengekspor DMA-BUF harus menyetel kolom exp_name
dari struct dma_buf_export_info
dengan benar ke nama eksportir sebelum memanggil API dma_buf_export()
untuk membuat DMA-BUF. Hal ini diperlukan untuk libdmabufinfo
dan alat dmabuf_dump
untuk memperoleh statistik per-eksportir yang kemudian diekspos dalam laporan bug.
Alat dmabuf_dump telah dimodifikasi untuk menampilkan informasi ini dengan argumen baru, -b
.
Statistik untuk kerangka tumpukan DMA-BUF
ION di GKI 2.0 tidak lagi digunakan dan digantikan dengan framework heaps DMA-BUF , yang merupakan bagian dari kernel linux upstream.
Statistik ION global berikut dilacak di Android 11:
- Ukuran total DMA-BUF yang diekspor oleh setiap tumpukan ION
- Ukuran total memori pra-alokasi yang tidak terpakai yang disimpan oleh setiap heap ION
Tidak ada antarmuka yang tersedia untuk mengekspos statistik heap per-ION di Android 11.
Tabel berikut membandingkan antarmuka statistik ION dengan antarmukanya untuk perangkat yang menggunakan framework heap DMA-BUF di Android 12.
Android 11 atau Perangkat diluncurkan dengan dukungan ION di Android 12 | Perangkat diluncurkan dengan tumpukan DMA-BUF di Android 12 | |
---|---|---|
Statistik ION per tumpukan | Tidak ada | Diurai dari statistik sysfs DMA-BUF |
Ukuran total DMA-BUF yang diekspor | /sys/kernel/ion/total_heap_size_kb (Tidak termasuk ukuran DMA-BUF yang diekspor oleh eksportir non-ION) | Diurai dari statistik sysfs DMA-BUF (termasuk ukuran seluruh DMA-BUF yang diekspor). |
Total memori dikumpulkan berdasarkan tumpukan | /sys/kernel/ion/total_pool_size_kb | /sys/kernel/dma_heap/total_pool_size_kb |
Meningkatkan akurasi perhitungan RAM yang hilang
Sebelumnya perhitungan RAM yang hilang dilakukan sebagai berikut:
final long lostRAM
= memInfo.getTotalSizeKb(
) - ( totalPss
- totalSwapPss
)
- memInfo.getFreeSizeKb()
- memInfo.getCachedSizeKb()
- kernelUsed
- memInfo.getZramTotalSizeKb()
;
Komponen totalPss
mencakup penggunaan memori GPU (dikembalikan oleh antarmuka getMemory() Memtrack HAL). Komponen kernelUsed
mencakup total penggunaan memori DMA-BUF. Namun, untuk perangkat Android, memori GPU berasal dari berikut ini:
- Alokasi langsung dilakukan oleh driver GPU menggunakan pengalokasi halaman fisik
- DMA-BUF dipetakan ke dalam ruang alamat GPU
Oleh karena itu, DMA-BUF yang dipetakan memori ke dalam ruang alamat GPU dikurangi dua kali saat kehilangan RAM dihitung. Android 12 mengimplementasikan solusi untuk menghitung ukuran DMA-BUF yang dipetakan ke dalam ruang alamat GPU, yang berarti ukuran tersebut hanya diperhitungkan satu kali dalam penghitungan RAM yang Hilang.
Detail solusinya adalah sebagai berikut:
- Memtrack HAL API
getMemory()
ketika dipanggil dengan PID 0 harus melaporkan total memori pribadi GPU global, untuk MemtrackType::GL dan MemtrackRecord::FLAG_SMAPS_UNACCOUNTED. - getMemory() ketika dipanggil dengan
PID
0
untukMemtrackType
selainGL
tidak boleh gagal. Sebaliknya, ia harus mengembalikan 0. - Solusi tracepoint/eBPF memori GPU yang ditambahkan di Android 12 menyumbang total memori GPU. Mengurangi total memori pribadi GPU dari total memori GPU akan menghasilkan ukuran DMA-BUF yang dipetakan ke dalam ruang alamat GPU. Nilai tersebut kemudian dapat digunakan untuk meningkatkan akurasi penghitungan RAM yang Hilang dengan memperhitungkan penggunaan memori GPU dengan benar.
- Memori GPU pribadi disertakan dalam
totalPss
di sebagian besar implementasi Memtrack HAL dan oleh karena itu harus dihapus duplikatnya sebelum menghapusnya darilostRAM
.
Solusi yang diterapkan dirinci di bagian berikutnya.
Hapus variabilitas Memtrack dari RAM yang hilang
Karena implementasi Memtrack HAL dapat bervariasi antar mitra, memori GPU yang disertakan dalam totalPSS
dari HAL tidak selalu konsisten. Untuk menghilangkan variabilitas dari lostRAM
, memori yang diperhitungkan dalam MemtrackType::GRAPHICS
dan MemtrackType::GL
dihapus dari totalPss
selama penghitungan lostRAM
.
Memori MemtrackType::GRAPHICS
dihapus dari totalPss
dan diganti dengan memori totalExportedDmabuf
dalam penghitungan lostRAM
di ActivityManagerService.java seperti yang ditunjukkan di bawah ini:
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;
Memori MemtrackType::GL
dihapus dari totalPss
dan diganti dengan memori GPU pribadi ( gpuPrivateUsage
) dalam penghitungan lostRAM
di ActivityManagerService.java seperti yang ditunjukkan di bawah ini:
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;
Memperbarui perhitungan RAM yang hilang
Total memori GPU pribadi dan total memori buffer DMA yang diekspor terdapat dalam kernelUsed + totalPss
yang dihapus dari lostRAM
. Hal ini menghilangkan variabilitas penghitungan ganda dan Memtrack dari perhitungan RAM yang hilang.
final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- kernelUsed - memInfo.getZramTotalSizeKb();
Validasi
Pengujian VTS menerapkan aturan bahwa perangkat yang diluncurkan di Android 12 dengan kernel Linux versi 5.4 atau lebih tinggi mendukung API getGpuDeviceInfo() .
Memtrack HAL API getGpuDeviceInfo()
baru harus mengembalikan informasi tentang perangkat GPU yang digunakan.
Hal ini memberikan penghitungan memori yang lebih baik dan visibilitas terhadap buffer DMA dan penggunaan memori GPU. Terapkan memtrack AIDL HAL untuk kehilangan RAM dan penghitungan memori dengan lebih baik. Fitur ini tidak bergantung pada layanan Google.
Penerapan
Fitur ini bergantung pada AIDL Memtrack HAL , dan petunjuk penerapannya di Android 12 disertakan dalam kode sebagai komentar.
Semua HIDL HAL direncanakan akan dikonversi ke AIDL pada rilis mendatang.
API berikut telah ditambahkan ke core/java/android/os/Debug.java
:
/**
* 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();
Untuk memastikan versi Anda berfungsi sebagaimana mestinya, integrasikan titik jejak di driver GPU Anda, dan terapkan AIDL memtrack HAL getMemory()
API untuk mengembalikan total memori pribadi GPU global dengan benar saat dipanggil dengan PID 0 untuk MemtrackType::GL dan MemtrackRecord:: FLAG_SMAPS_UNACCOUNTED.