หน้านี้อธิบายการปรับปรุงการบัญชีหน่วยความจำต่างๆ ที่นำมาใช้ใน Android 12
สถิติ DMA-BUF ใน sysfs
ใน Android 11 และ Android 12 ไม่สามารถติดตั้ง debugfs
ใน User builds ได้ ดังนั้นจึงมีการเพิ่มสถิติ 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 แยกวิเคราะห์สถิติ 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 อัปสตรีม
สถิติ 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 ที่หายไปทำได้ดังนี้:
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 จะถูกลบออกสองครั้งเมื่อมีการคำนวณ 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
หน่วยความจำจะถูกลบออกจาก 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
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