หน้านี้อธิบายการปรับปรุงการบัญชีหน่วยความจำต่างๆ ที่เปิดตัวใน Android 12
สถิติ DMA-BUF ใน sysfs
ใน Android 11 และ Android 12 debugfs จะ
ติดตั้งในบิลด์ของผู้ใช้ไม่ได้ เราจึงได้เพิ่มสถิติ DMA-BUF ลงใน sysfs ในไดเรกทอรี
/sys/kernel/dmabuf/buffers ใน Android 12
| เส้นทาง | คำอธิบาย | 
|---|---|
/sys/kernel/dmabuf/buffers
    | 
    ไดเรกทอรี /sys/kernel/dmabuf/buffers มี
      สแนปชอตของสถานะภายในของ DMA-BUF ทุกรายการ
   /sys/kernel/dmabuf/buffers/<inode_number> มีสถิติสำหรับ DMA-BUF ที่มีหมายเลข inode ที่ไม่ซ้ำกัน
      <inode_number>
    | 
  
/sys/kernel/dmabuf/buffers/<inode_number>/exporter_name
    | 
   ไฟล์แบบอ่านอย่างเดียวนี้มีชื่อของโปรแกรมส่งออก DMA-BUF | 
/sys/kernel/dmabuf/buffers/<inode_number>/size
    | 
   ไฟล์แบบอ่านอย่างเดียวนี้จะระบุขนาดของ DMA-BUF ในหน่วยไบต์ | 
API libdmabufinfo จะแยกวิเคราะห์สถิติ DMA-BUF sysfs เพื่อแสดง
สถิติแต่ละตัวส่งออกและแต่ละบัฟเฟอร์
ไดรเวอร์เคอร์เนลที่ส่งออก DMA-BUF ต้องตั้งค่าฟิลด์ exp_name ของ struct dma_buf_export_info ให้ถูกต้องเป็นชื่อผู้ส่งออกก่อนเรียกใช้ API dma_buf_export() เพื่อสร้าง DMA-BUF ซึ่งจำเป็นสำหรับlibdmabufinfo
และเครื่องมือ dmabuf_dump ในการรับสถิติต่อผู้ส่งออก จากนั้นจะ
แสดงในรายงานข้อบกพร่อง
เราได้แก้ไขเครื่องมือ dmabuf_dump เพื่อแสดงข้อมูลนี้ด้วยอาร์กิวเมนต์ใหม่ -b
สถิติสำหรับเฟรมเวิร์กฮีป DMA-BUF
เราจะเลิกใช้งาน ION ใน GKI 2.0 เพื่อใช้เฟรมเวิร์กฮีป DMA-BUF แทน ซึ่งเป็นส่วนหนึ่งของเคอร์เนล Linux ต้นทาง
ระบบจะติดตามสถิติ ION ทั่วโลกต่อไปนี้ใน Android 11
- ขนาดรวมของ DMA-BUF ที่ส่งออกโดยกอง ION ทุกกอง
 - ขนาดรวมของหน่วยความจำที่จัดสรรล่วงหน้าที่ไม่ได้ใช้ซึ่งจัดเก็บโดยฮีป ION ทุกรายการ
 
ไม่มีอินเทอร์เฟซที่พร้อมใช้งานเพื่อแสดงสถิติฮีปต่อ ION ใน Android 11
ตารางต่อไปนี้เปรียบเทียบอินเทอร์เฟซสถิติ ION กับอินเทอร์เฟซที่เทียบเท่าสำหรับอุปกรณ์ที่ใช้เฟรมเวิร์กฮีป DMA-BUF ใน Android 12
| Android 11 หรืออุปกรณ์ที่เปิดตัวพร้อมรองรับ ION ใน Android 12 | อุปกรณ์ที่เปิดตัวพร้อมฮีป DMA-BUF ใน Android 12 | |
|---|---|---|
| สถิติ ION ต่อฮีป | ไม่มี | แยกวิเคราะห์จากสถิติ sysfs ของ DMA-BUF | 
| ขนาดรวมของ DMA-BUF ที่ส่งออก | /sys/kernel/ion/total_heap_size_kb
     (ไม่รวมขนาดของ DMA-BUF ที่ส่งออกโดยผู้ส่งออกที่ไม่ใช่ ION)  | 
   แยกวิเคราะห์จากสถิติ sysfs ของ DMA-BUF
      (รวมขนาดของ DMA-BUF ทั้งหมดที่ส่งออก)  | 
  
| หน่วยความจำทั้งหมดที่จัดกลุ่มตามฮีป | /sys/kernel/ion/total_pool_size_kb | 
   /sys/kernel/dma_heap/total_pool_size_kb | 
  
ปรับปรุงความแม่นยำในการคำนวณ RAM ที่สูญเสียไป
ก่อนหน้านี้ การคำนวณ RAM ที่สูญเสียไปทำได้ดังนี้
final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- kernelUsed - memInfo.getZramTotalSizeKb();
คอมโพเนนต์ totalPss มีการใช้งานหน่วยความจำ GPU (ส่งคืนโดยอินเทอร์เฟซ getMemory()
ของ Memtrack HAL) คอมโพเนนต์ kernelUsed มีการใช้งานหน่วยความจำ DMA-BUF ทั้งหมด
อย่างไรก็ตาม สำหรับอุปกรณ์ Android หน่วยความจำ GPU มาจากแหล่งที่มาต่อไปนี้
- การจัดสรรโดยตรงที่ไดรเวอร์ GPU ทำโดยใช้ตัวจัดสรรหน้าจริง
 - แมป DMA-BUF ลงในพื้นที่ที่อยู่ GPU
 
ดังนั้น DMA-BUF ที่แมปหน่วยความจำลงในพื้นที่ที่อยู่ GPU จึงถูก หักออก 2 ครั้งเมื่อคำนวณ RAM ที่สูญเสียไป Android 12 ใช้โซลูชันในการคำนวณขนาดของ DMA-BUF ที่แมปกับพื้นที่ที่อยู่ของ GPU ซึ่งหมายความว่าระบบจะนับรวม เพียงครั้งเดียวในการคำนวณ RAM ที่สูญเสียไป
รายละเอียดของโซลูชันมีดังนี้
- เมื่อเรียกใช้ Memtrack HAL API 
getMemory()ด้วย PID 0 จะต้องรายงาน หน่วยความจำส่วนตัวของ GPU ทั้งหมดทั่วโลกสำหรับMemtrackType::GLและMemtrackRecord::FLAG_SMAPS_UNACCOUNTED getMemory()เมื่อเรียกใช้ด้วยPID 0สำหรับMemtrackTypeอื่นที่ไม่ใช่GLต้องไม่ล้มเหลว แต่ต้องแสดงผลเป็น 0 แทน- โซลูชันจุดติดตามหน่วยความจำ GPU/eBPF ที่เพิ่มใน Android 12 จะพิจารณาหน่วยความจำ GPU ทั้งหมด การลบ หน่วยความจำส่วนตัวทั้งหมดของ GPU ออกจากหน่วยความจำทั้งหมดของ GPU จะได้ขนาดของ DMA-BUF ที่แมปกับพื้นที่ที่อยู่ของ GPU จากนั้นจะใช้ค่าดังกล่าวเพื่อ ปรับปรุงความแม่นยำของการคำนวณ RAM ที่สูญเสียไปโดยการพิจารณา การใช้งานหน่วยความจำ GPU อย่างถูกต้อง
 - หน่วยความจำ GPU ส่วนตัวรวมอยู่ใน 
totalPssในการติดตั้งใช้งาน Memtrack HAL ส่วนใหญ่ จึงต้องทำการซ้ำกันก่อนที่จะนำออกจากlostRAM 
โปรดดูรายละเอียดโซลูชันที่ใช้ในส่วนถัดไป
นำความแปรปรวนของ Memtrack ออกจาก RAM ที่สูญเสียไป
เนื่องจากการติดตั้งใช้งาน Memtrack HAL อาจแตกต่างกันไปในแต่ละพาร์ทเนอร์ หน่วยความจำ GPU
ที่รวมอยู่ใน totalPSS จาก HAL จึงอาจไม่สอดคล้องกันเสมอไป หากต้องการนำความแปรปรวนออกจาก lostRAM ระบบจะนำหน่วยความจำที่พิจารณาใน MemtrackType::GRAPHICS
และ MemtrackType::GL ออกจาก totalPss ระหว่างการคำนวณ lostRAM
ระบบจะนำหน่วยความจำ MemtrackType::GRAPHICS ออกจาก totalPss และแทนที่ด้วย
หน่วยความจำ totalExportedDmabuf ในการคำนวณ lostRAM ใน
ActivityManagerService.java ดังที่แสดงในโค้ดต่อไปนี้
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 memory จะถูกนำออกจาก totalPss และแทนที่ด้วย
หน่วยความจำ GPU ส่วนตัว (gpuPrivateUsage) ในการคำนวณ lostRAM ใน
ActivityManagerService.java ดังที่แสดงในโค้ดต่อไปนี้
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;
การคำนวณ RAM ที่สูญเสียไปที่อัปเดตแล้ว
ทั้งหน่วยความจำ GPU ส่วนตัวทั้งหมดและหน่วยความจำบัฟเฟอร์ DMA ที่ส่งออกทั้งหมดจะ
อยู่ใน kernelUsed + totalPss ซึ่งนำออกจาก lostRAM ซึ่งจะ
ขจัดการนับซ้ำและความแปรปรวนของ Memtrack จากการคำนวณ RAM ที่สูญเสียไป
final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- kernelUsed - memInfo.getZramTotalSizeKb();
การตรวจสอบความถูกต้อง
การทดสอบ VTS บังคับใช้กฎที่ว่าอุปกรณ์ที่เปิดตัวใน Android
12 ที่มี Linux Kernel เวอร์ชัน 5.4 ขึ้นไปต้องรองรับ
API getGpuDeviceInfo()
API ของ Memtrack HAL ใหม่ getGpuDeviceInfo() ต้องแสดงข้อมูลเกี่ยวกับ
อุปกรณ์ GPU ที่ใช้งานอยู่
ซึ่งจะช่วยให้การบัญชีหน่วยความจำและการมองเห็นบัฟเฟอร์ DMA และการใช้หน่วยความจำ GPU ดีขึ้น ใช้ memtrack AIDL HAL เพื่อการบัญชี RAM และหน่วยความจำที่สูญหายที่ดีขึ้น ฟีเจอร์นี้ไม่ได้ขึ้นอยู่กับบริการของ Google
การใช้งาน
ฟีเจอร์นี้ขึ้นอยู่กับ AIDL Memtrack HAL และคำแนะนำในการ ติดตั้งใช้งานใน Android 12 จะรวมอยู่ในโค้ด เป็นความคิดเห็น เราวางแผนที่จะแปลง HIDL HAL ทั้งหมดเป็น AIDL ในรุ่นต่อๆ ไป
เราได้เพิ่ม API ต่อไปนี้ลงใน 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();
หากต้องการยืนยันว่าเวอร์ชันของคุณทํางานตามที่ต้องการ ให้ผสานรวมจุดติดตามใน
ไดรเวอร์ GPU และใช้ AIDL memtrack HAL getMemory() API เพื่อ
แสดงผลหน่วยความจำส่วนตัวทั้งหมดของ GPU ทั่วโลกอย่างถูกต้องเมื่อเรียกใช้ด้วย PID 0 สําหรับ MemtrackType::GL และ MemtrackRecord::FLAG_SMAPS_UNACCOUNTED