หน้านี้จะอธิบายถึงการปรับปรุงบัญชีหน่วยความจำต่างๆ ที่เริ่มใช้ใน 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 ที่ไม่ซ้ำกัน <inode_number>
|
/sys/kernel/dmabuf/buffers/<inode_number>/exporter_name
|
ไฟล์แบบอ่านอย่างเดียวนี้มีชื่อของผู้ส่งออก DMA-BUF |
/sys/kernel/dmabuf/buffers/<inode_number>/size
|
ไฟล์แบบอ่านอย่างเดียวนี้ระบุขนาดของ DMA-BUF ในหน่วยไบต์ |
libdmabufinfo
API จะแยกวิเคราะห์สถิติ sysfs
ของ DMA-BUF เพื่อแสดงสถิติต่อผู้ส่งออกและสถิติต่อบัฟเฟอร์
โปรดทราบว่าไดรเวอร์เคอร์เนลที่ส่งออก 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 เวอร์ชัน upstream
มีการติดตามสถิติ 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) |
แยกวิเคราะห์จากสถิติ DMA-BUF sysfs
(รวมขนาดของ 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 memory tracepoint/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 และใช้ AIDL memtrack HAL getMemory()
API เพื่อให้แสดงหน่วยความจําส่วนตัวทั้งหมดของ GPU ทั่วโลกอย่างถูกต้องเมื่อเรียกใช้ด้วย PID 0 สําหรับ MemtrackType::GL และ MemtrackRecord::FLAG_SMAPS_UNACCOUNTED