Halaman ini menjelaskan berbagai peningkatan penghitungan memori yang diperkenalkan di Android 12.
Statistik DMA-BUF di sysfs
Di Android 11 dan Android 12, debugfs tidak dapat di-mount di build Pengguna. Jadi, statistik DMA-BUF telah ditambahkan ke sysfs di
direktori /sys/kernel/dmabuf/buffers di Android 12.
| Jalur | Deskripsi | 
|---|---|
/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 hanya baca ini berisi nama eksportir DMA-BUF. | 
/sys/kernel/dmabuf/buffers/<inode_number>/size
    | 
   File hanya baca ini menentukan ukuran DMA-BUF dalam byte. | 
libdmabufinfo API mem-parsing statistik sysfs DMA-BUF untuk mengekspos statistik per-pengekspor dan per-buffer.
Driver kernel yang mengekspor DMA-BUF harus menyetel kolom exp_name dari
struct dma_buf_export_info dengan benar ke nama pengekspor sebelum memanggil
dma_buf_export() API untuk membuat DMA-BUF. Hal ini diperlukan agar libdmabufinfo
dan alat dmabuf_dump dapat memperoleh statistik per-pengekspor, yang kemudian
ditampilkan dalam laporan bug.
Alat dmabuf_dump telah diubah untuk menampilkan informasi ini dengan argumen baru, -b.
Statistik untuk framework heap DMA-BUF
ION di GKI 2.0 tidak digunakan lagi dan digantikan dengan framework heap DMA-BUF, yang merupakan bagian dari kernel Linux upstream.
Statistik ION global berikut dilacak di Android 11:
- Total ukuran DMA-BUF yang diekspor oleh setiap heap ION
 - Total ukuran memori yang telah dialokasikan sebelumnya dan tidak digunakan 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 antarmuka yang setara untuk perangkat yang menggunakan framework heap DMA-BUF di Android 12.
| Android 11 atau perangkat yang diluncurkan dengan dukungan ION di Android 12 | Perangkat yang diluncurkan dengan heap DMA-BUF di Android 12 | |
|---|---|---|
| Statistik ION per heap | Tidak ada | Diuraikan dari statistik sysfs DMA-BUF | 
| Ukuran total DMA-BUF yang diekspor | /sys/kernel/ion/total_heap_size_kb
     (Tidak mencakup ukuran DMA-BUF yang diekspor oleh pengekspor non-ION)  | 
   Diuraikan dari statistik sysfs DMA-BUF
      (mencakup ukuran semua DMA-BUF yang diekspor).  | 
  
| Total memori yang dikumpulkan oleh heap | /sys/kernel/ion/total_pool_size_kb | 
   /sys/kernel/dma_heap/total_pool_size_kb | 
  
Meningkatkan akurasi perhitungan RAM yang hilang
Sebelumnya, penghitungan RAM yang hilang dilakukan sebagai berikut:
final panjang lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- kernelUsed - memInfo.getZramTotalSizeKb();
Komponen totalPss mencakup penggunaan memori GPU (yang ditampilkan 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 yang dilakukan oleh driver GPU menggunakan pengalokasi halaman fisik
 - DMA-BUF dipetakan ke ruang alamat GPU
 
Oleh karena itu, DMA-BUF yang dipetakan ke memori dalam ruang alamat GPU dikurangi dua kali saat RAM yang hilang dihitung. Android 12 menerapkan solusi untuk menghitung ukuran DMA-BUF yang dipetakan ke ruang alamat GPU, yang berarti bahwa DMA-BUF diperhitungkan hanya sekali dalam penghitungan RAM yang Hilang.
Detail solusinya adalah sebagai berikut:
- Memtrack HAL API 
getMemory()saat dipanggil dengan PID 0 harus melaporkan total memori pribadi GPU global, untukMemtrackType::GLdanMemtrackRecord::FLAG_SMAPS_UNACCOUNTED. getMemory()saat dipanggil denganPID 0untukMemtrackTypeselainGLtidak boleh gagal. Sebagai gantinya, fungsi ini harus menampilkan 0.- Solusi titik rekaman aktivitas/eBPF memori GPU yang ditambahkan di Android 12 memperhitungkan total memori GPU. Dengan mengurangi total memori pribadi GPU dari total memori GPU, Anda akan mendapatkan ukuran DMA-BUF yang dipetakan ke ruang alamat GPU. Nilai ini kemudian dapat digunakan untuk meningkatkan akurasi perhitungan RAM yang Hilang dengan memperhitungkan penggunaan memori GPU dengan benar.
 - Memori GPU pribadi disertakan dalam 
totalPssdi sebagian besar implementasi HAL Memtrack dan oleh karena itu, harus dideduplikasi sebelum dihapus darilostRAM. 
Solusi yang diterapkan dijelaskan di bagian berikutnya.
Menghapus variabilitas Memtrack dari RAM yang hilang
Karena implementasi Memtrack HAL dapat bervariasi di seluruh partner, 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 perhitungan lostRAM di
ActivityManagerService.java seperti yang ditunjukkan dalam kode berikut:
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 perhitungan lostRAM di
ActivityManagerService.java seperti yang ditunjukkan dalam kode berikut:
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 yang hilang diperbarui
Total memori GPU pribadi dan total memori buffer DMA yang diekspor
terkandung dalam kernelUsed + totalPss yang dihapus dari lostRAM. Hal ini
menghilangkan penghitungan ganda dan variabilitas 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 yang lebih tinggi mendukung API getGpuDeviceInfo().
Memtrack HAL API baru getGpuDeviceInfo() harus menampilkan informasi tentang
perangkat GPU yang sedang digunakan.
Hal ini memberikan akuntansi memori yang lebih baik dan visibilitas ke dalam penggunaan memori GPU dan buffer DMA. Menerapkan HAL AIDL memtrack untuk akuntansi memori dan RAM yang hilang yang lebih baik. Fitur ini tidak bergantung pada layanan Google.
Implementasi
Fitur ini bergantung pada AIDL Memtrack HAL, dan petunjuk untuk menerapkannya di Android 12 disertakan dalam kode sebagai komentar. Semua HAL HIDL direncanakan akan dikonversi ke AIDL dalam 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 memverifikasi bahwa versi Anda berfungsi sebagaimana mestinya, integrasikan titik pelacakan 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.