หน้านี้อธิบายการปรับปรุงการบัญชีหน่วยความจำต่างๆ ที่เปิดตัวใน Android 12
สถิติ DMA-BUF ใน sysf
ใน 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_number>
|
/sys/kernel/dmabuf/buffers/<inode_number>/exporter_name
|
ไฟล์แบบอ่านอย่างเดียวนี้มีชื่อของผู้ส่งออก DMA-BUF |
/sys/kernel/dmabuf/buffers/<inode_number>/size
|
ไฟล์แบบอ่านอย่างเดียวนี้จะระบุขนาดของ DMA-BUF เป็นไบต์ |
libdmabufinfo
API จะแยกวิเคราะห์สถิติ DMA-BUF sysfs
เพื่อแสดงสถิติต่อผู้ส่งออกและต่อบัฟเฟอร์
โปรดทราบว่าไดรเวอร์เคอร์เนลที่ส่งออก DMA-BUF ต้องตั้งค่าฟิลด์ exp_name
ของ struct dma_buf_export_info
เป็นชื่อผู้ส่งออกอย่างถูกต้อง ก่อนที่จะเรียกใช้ dma_buf_export()
API เพื่อสร้าง 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 ต่อกอง | ไม่มี | แยกวิเคราะห์จากสถิติ DMA-BUF sysfs |
ขนาดรวมของ 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 ที่สูญหายมีดังนี้
ความยาวสุดท้าย 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 แทน - โซลูชัน Tracepoint ของหน่วยความจำ GPU/eBPF ที่เพิ่มเข้ามาในบัญชี Android 12 สำหรับหน่วยความจำ GPU ทั้งหมด การลบหน่วยความจำส่วนตัวของ GPU ทั้งหมดจากหน่วยความจำ GPU ทั้งหมดจะทำให้ขนาดของ DMA-BUF ที่แมปลงในพื้นที่ที่อยู่ของ GPU จากนั้นระบบจะนำค่าดังกล่าวมาใช้เพื่อปรับปรุงความแม่นยำของการคำนวณ RAM ที่สูญหายโดยพิจารณาการใช้งานหน่วยความจำ GPU อย่างถูกต้อง
- หน่วยความจํา GPU ส่วนตัวจะรวมอยู่ใน
totalPss
ในการใช้งาน HAL ของ Memtrack ส่วนใหญ่ จึงต้องกรองข้อมูลที่ซ้ำกันออกก่อนนําออกจากlostRAM
วิธีแก้ปัญหาที่นำไปใช้จะแสดงรายละเอียดในส่วนถัดไป
นำความแปรปรวนของ Memtrack ออกจาก RAM ที่หายไป
เนื่องจากการใช้งาน HAL ของ Memtrack อาจแตกต่างกันไปในแต่ละพาร์ทเนอร์ หน่วยความจำ 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
ออกจาก 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 เวอร์ชัน 5.4 ขึ้นไปต้องรองรับ API getGpuDeviceInfo()
Memtrack HAL API ใหม่ 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 และใช้ Memtrack HAL getMemory()
API ของ AIDL เพื่อแสดงหน่วยความจำ GPU ส่วนตัวทั้งหมดทั่วโลกอย่างถูกต้องเมื่อเรียกใช้ด้วย PID 0 สำหรับ MemtrackType::GL
และ MemtrackRecord::FLAG_SMAPS_UNACCOUNTED