이 페이지에서는 Android 12에서 도입된 다양한 메모리 계산 개선사항을 설명합니다.
sysfs의 DMA-BUF 통계
Android 11과 Android 12에서는 debugfs
를 사용자 빌드에 마운트할 수 없습니다. 따라서 DMA-BUF 통계가 Android 12의 /sys/kernel/dmabuf/buffers
디렉터리에 있는 sysfs
에 추가되었습니다.
경로 | 설명 |
---|---|
/sys/kernel/dmabuf/buffers
|
/sys/kernel/dmabuf/buffers 디렉터리에는 모든 DMA-BUF의 내부 상태 스냅샷이 포함되어 있습니다.
/sys/kernel/dmabuf/buffers/<inode_number> 에는 고유한 inode 번호 <inode_number> 가 있는 DMA-BUF 통계가 포함되어 있습니다.
|
/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를 내보내는 커널 드라이버는 dma_buf_export()
API를 호출하여 DMA-BUF를 만들기 전에 struct dma_buf_export_info
의 exp_name
필드를 내보내기 이름으로 올바르게 설정해야 합니다.
이는 libdmabufinfo
및 dmabuf_dump
도구가 버그 신고에 노출될 내보내기별 통계를 추출하는 데 필요합니다.
dmabuf_dump 도구는 이 정보를 새 인수 -b
와 함께 출력하도록 수정되었습니다.
DMA-BUF 힙 프레임워크 통계
GKI 2.0의 ION이 지원 중단되고 업스트림 Linux 커널의 일부인 DMA-BUF 힙 프레임워크로 대체됩니다.
다음 전역 ION 통계는 Android 11에서 추적됩니다.
- 모든 ION 힙에서 내보낸 DMA-BUF의 총 크기
- 모든 ION 힙에서 저장한 사용되지 않은 사전 할당 메모리의 총 크기
Android 11에는 ION별 힙 통계를 노출하는 데 사용할 수 있는 인터페이스가 없습니다.
다음 표는 ION 통계 인터페이스를 Android 12에서 DMA-BUF 힙 프레임워크를 사용하는 기기의 ION 통계 인터페이스와 비교합니다.
Android 11 또는 Android 12에서 ION 지원이 적용되어 출시되는 기기 | Android 12에서 DMA-BUF 힙이 적용되어 출시되는 기기 | |
---|---|---|
힙당 ION 통계 | 없음 | DMA-BUF sysfs 통계에서 파싱됨 |
내보낸 DMA-BUF의 총 크기 | /sys/kernel/ion/total_heap_size_kb
(ION이 아닌 내보내기에서 내보낸 DMA-BUF 크기는 포함되지 않음) |
DMA-BUF sysfs 통계에서 파싱됨
(내보낸 모든 DMA-BUF의 크기 포함) |
힙에서 풀링된 총 메모리 | /sys/kernel/ion/total_pool_size_kb |
/sys/kernel/dma_heap/total_pool_size_kb |
손실된 RAM 계산 정확도 개선
이전에는 손실된 RAM을 다음과 같이 계산했습니다.
최종 long lostRAM
= memInfo.getTotalSizeKb(
) - (totalPss
- totalSwapPss
)
- memInfo.getFreeSizeKb()
- memInfo.getCachedSizeKb()
- kernelUsed
- memInfo.getZramTotalSizeKb()
;
totalPss
구성요소에는 GPU 메모리 사용량(Memtrack HAL의 getMemory() 인터페이스에서 반환)이 포함되었습니다. kernelUsed
구성요소에는 총 DMA-BUF 메모리 사용량이 포함되었습니다.
그러나 Android 기기의 경우 GPU 메모리 출처는 다음과 같습니다.
- 실제 페이지 할당자를 사용하여 GPU 드라이버에서 직접 할당
- GPU 주소 공간에 매핑된 DMA-BUF
따라서 GPU 주소 공간에 메모리 매핑된 DMA-BUF는 손실된 RAM을 계산할 때 두 번 뺐습니다. Android 12는 GPU 주소 공간에 매핑된 DMA-BUF의 크기를 계산하는 솔루션을 구현합니다. 즉, 손실된 RAM 계산에서 한 번만 고려됩니다.
솔루션 세부정보는 다음과 같습니다.
- PID 0으로 호출될 때 Memtrack HAL API
getMemory()
는 MemtrackType::GL 및 MemtrackRecord::FLAG_SMAPS_UNACCOUNTED의 전역 총 GPU 비공개 메모리를 보고해야 합니다. GL
이 아닌MemtrackType
의PID
0
으로 호출될 때 getMemory()는 실패해서는 안 됩니다. 대신 0을 반환해야 합니다.- Android 12에서 추가된 GPU 메모리 tracepoint/eBPF 솔루션은 총 GPU 메모리를 고려합니다. 총 GPU 메모리에서 총 GPU 비공개 메모리를 빼면 GPU 주소 공간에 매핑된 DMA-BUF 크기가 제공됩니다. 이 값은 GPU 메모리 사용량을 올바르게 고려하여 손실된 RAM 계산의 정확성을 개선하는 데 사용할 수 있습니다.
- 비공개 GPU 메모리는 대부분의 Memtrack HAL 구현에서
totalPss
에 포함되어 있으므로lostRAM
에서 삭제하기 전에 중복 삭제해야 합니다.
구현된 솔루션은 다음 섹션에서 자세히 설명합니다.
손실된 RAM에서 Memtrack 가변성 삭제
Memtrack HAL 구현은 파트너마다 다를 수 있으므로 HAL의 totalPSS
에 포함된 GPU 메모리가 항상 일관된 것은 아닙니다. lostRAM
에서 가변성을 삭제하기 위해 MemtrackType::GRAPHICS
와 MemtrackType::GL
에서 고려된 메모리는 lostRAM
계산 중에 totalPss
에서 삭제됩니다.
MemtrackType::GRAPHICS
메모리는 totalPss
에서 삭제되고 아래와 같이 ActivityManagerService.java의 lostRAM
계산에서 totalExportedDmabuf
메모리로 대체됩니다.
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
에서 삭제되고 아래와 같이 ActivityManagerService.java의 lostRAM
계산에서 비공개 GPU 메모리(gpuPrivateUsage
)로 대체됩니다.
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 버퍼 메모리는 모두 lostRAM
에서 삭제된 kernelUsed + totalPss
에 포함됩니다. 이렇게 하면 손실된 RAM 계산으로 인한 이중 계산과 Memtrack 가변성이 모두 제거됩니다.
final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- kernelUsed - memInfo.getZramTotalSizeKb();
유효성 검사
VTS 테스트는 Linux 커널 버전 5.4 이상으로 Android 12에서 실행되는 기기가 getGpuDeviceInfo() API를 지원한다는 규칙을 적용합니다.
새 Memtrack HAL API getGpuDeviceInfo()
는 사용 중인 GPU 기기에 관한 정보를 반환해야 합니다.
이를 통해 메모리 계산과 DMA 버퍼 및 GPU 메모리 사용량에 관한 가시성이 개선됩니다. 손실된 RAM 및 메모리 계산 개선을 위해 memtrack AIDL HAL을 구현합니다. 이 기능은 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 드라이버에서 tracepoint를 통합하고 MemtrackType::GL 및 MemtrackRecord::FLAG_SMAPS_UNACCOUNTED의 PID 0으로 호출될 때 전역 총 GPU 비공개 메모리를 올바르게 반환하도록 AIDL memtrack HAL getMemory()
API를 구현하세요.