หน้านี้อธิบายการปรับปรุงการบัญชีหน่วยความจำต่างๆ ที่เปิดตัวใน 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 ในหน่วยไบต์ |
libdmabufinfo
API จะแยกวิเคราะห์สถิติ 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 ต้นทาง
Android 11 จะติดตามสถิติ ION ทั่วโลกต่อไปนี้
- ขนาดรวมของ 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 ที่สูญเสียไปทำได้ดังนี้
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 ที่สูญเสียไป
รายละเอียดของโซลูชันมีดังนี้
- API ของ Memtrack HAL
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
ออกจาก 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 ขึ้นไปต้องรองรับ getGpuDeviceInfo() API
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