이 페이지에서는 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를 생성하기 위해 dma_buf_export()
API를 호출하기 전에 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 힙 프레임워크를 사용하는 기기의 해당 인터페이스와 비교합니다.
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 계산 정확도 개선
이전에는 손실된 램 계산이 다음과 같이 수행되었습니다.
최종 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의 크기를 계산하는 솔루션을 구현합니다. 즉, Lost 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 메모리 사용량을 올바르게 계산하여 Lost RAM 계산의 정확도를 높일 수 있습니다.
- 개인 GPU 메모리는 대부분의 Memtrack HAL 구현에서
totalPss
에 포함되어 있으므로lostRAM
에서 제거하기 전에 중복 제거해야 합니다.
구현된 솔루션은 다음 섹션에서 자세히 설명합니다.
손실된 RAM에서 Memtrack 변동성 제거
Memtrack HAL 구현은 파트너에 따라 다를 수 있으므로 HAL의 totalPSS
에 포함된 GPU 메모리가 항상 일관성이 있는 것은 아닙니다. lostRAM
에서 변동성을 제거하기 위해 MemtrackType::GRAPHICS
및 MemtrackType::GL
에서 설명된 메모리는 lostRAM
계산 중에 totalPss
에서 제거됩니다.
MemtrackType::GRAPHICS
메모리는 totalExportedDmabuf
에서 제거되고 아래와 같이 ActivityManagerService.java 의 lostRAM
계산에서 totalPss
메모리로 대체됩니다.
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 버퍼 메모리는 모두 kernelUsed + totalPss
에 포함되어 있으며 이는 lostRAM
에서 제거됩니다. 이것은 손실된 RAM 계산에서 이중 계산 및 Memtrack 변동성을 모두 제거합니다.
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 메모리 사용에 대한 더 나은 메모리 계정 및 가시성을 제공합니다. 더 나은 손실된 RAM 및 메모리 계정을 위해 memtrack AIDL HAL을 구현합니다. 이 기능은 Google 서비스에 종속되지 않습니다.
구현
이 기능은 AIDL Memtrack HAL 에 따라 다르며 Android 12에서 이를 구현하기 위한 지침이 코드에 주석으로 포함되어 있습니다.
모든 HIDL HAL은 향후 릴리스에서 AIDL로 변환될 예정입니다.
core/java/android/os/Debug.java
에 다음 API가 추가되었습니다.
/**
* 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를 구현하여 MemtrackType::GL 및 MemtrackRecord:에 대해 PID 0으로 호출할 때 전체 GPU 전용 메모리를 올바르게 반환합니다. FLAG_SMAPS_UNACCOUNTED.