Menerapkan DMABUF dan GPU Memory Accounting di Android 12

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 snapshot 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.

libdmabufinfo API mem-parsing statistik sysfs DMA-BUF untuk mengekspos statistik per-eksportir dan per-buffer.

Harap dicatat bahwa driver kernel yang mengekspor DMA-BUF harus menyetel bidang exp_name dari struct dma_buf_export_info dengan benar ke nama eksportir sebelum memanggil dma_buf_export() API untuk membuat DMA-BUF. Ini diperlukan untuk libdmabufinfo dan alat dmabuf_dump untuk mendapatkan 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 kerja tumpukan DMA-BUF

ION di GKI 2.0 tidak digunakan lagi untuk mendukung kerangka kerja 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 tumpukan ION

Tidak ada antarmuka yang tersedia untuk mengekspos statistik heap per-ION di Android 11.

Tabel berikut membandingkan antarmuka statistik ION dengan rekan-rekannya untuk perangkat yang menggunakan kerangka kerja 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 semua DMA-BUF yang diekspor).
Total memori dikumpulkan oleh 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:

akhir lama lostRAM = memInfo.getTotalSizeKb( ) - ( totalPss - totalSwapPss )

- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()

- kernelUsed - memInfo.getZramTotalSizeKb() ;

Komponen totalPss termasuk penggunaan memori GPU (dikembalikan oleh antarmuka getMemory() Memtrack HAL). Komponen kernelUsed termasuk total penggunaan memori DMA-BUF. Namun, untuk perangkat Android, memori GPU berasal dari berikut ini:

  • Alokasi langsung yang dibuat 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 ketika RAM yang hilang dihitung. Android 12 mengimplementasikan solusi untuk menghitung ukuran DMA-BUF yang dipetakan ke dalam ruang alamat GPU, yang berarti hanya dihitung sekali dalam perhitungan Lost RAM.

Rincian penyelesaiannya adalah sebagai berikut:

  • Memtrack HAL API getMemory() saat dipanggil dengan PID 0 harus melaporkan total memori pribadi GPU global, untuk MemtrackType::GL dan MemtrackRecord::FLAG_SMAPS_UNACCOUNTED.
  • getMemory() saat dipanggil dengan PID 0 untuk MemtrackType selain GL tidak boleh gagal. Itu malah 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 memberikan ukuran DMA-BUF yang dipetakan ke dalam ruang alamat GPU. Nilai tersebut kemudian dapat digunakan untuk meningkatkan akurasi perhitungan Lost RAM dengan menghitung penggunaan memori GPU dengan benar.
  • Memori GPU pribadi disertakan dalam totalPss di sebagian besar implementasi HAL Memtrack dan oleh karena itu harus diduplikasi sebelum menghapusnya dari lostRAM .

Solusi yang diterapkan dirinci di bagian berikutnya.

Menghapus 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 menghapus variabilitas dari lostRAM , memori yang diperhitungkan dalam MemtrackType::GRAPHICS dan MemtrackType::GL dihapus dari totalPss selama perhitungan lostRAM .

MemtrackType::GRAPHICS dihapus dari totalPss dan diganti dengan memori totalExportedDmabuf dalam perhitungan 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;

MemtrackType::GL dihapus dari totalPss dan diganti dengan memori GPU pribadi ( gpuPrivateUsage ) dalam perhitungan 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;

Perhitungan RAM hilang yang diperbarui

Baik total memori GPU privat maupun total memori buffer DMA yang diekspor terkandung dalam kernelUsed + totalPss yang dihapus dari lostRAM . 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 getGpuDeviceInfo() API.

Memtrack HAL API getGpuDeviceInfo() baru harus mengembalikan informasi tentang perangkat GPU yang digunakan.

Ini memberikan penghitungan memori yang lebih baik dan visibilitas ke buffer DMA dan penggunaan memori GPU. Menerapkan memtrack AIDL HAL untuk RAM dan memori yang hilang dengan lebih baik. Fitur ini tidak bergantung pada layanan Google.

Penerapan

Fitur ini bergantung pada AIDL Memtrack HAL , dan petunjuk untuk mengimplementasikannya di Android 12 disertakan dalam kode sebagai komentar.

Semua HIDL HAL direncanakan untuk dikonversi ke AIDL di 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 dimaksud, integrasikan tracepoints 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.