На этой странице описаны различные улучшения учета памяти, представленные в 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 в байтах. | 
 API-интерфейс libdmabufinfo анализирует статистику 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 framework
ION в GKI 2.0 устарел в пользу инфраструктуры куч DMA-BUF , которая является частью исходного ядра Linux.
В Android 11 отслеживается следующая глобальная статистика ION:
- Общий размер DMA-BUF, экспортируемых каждой ION-кучей
- Общий размер неиспользуемой предварительно выделенной памяти, хранящейся в каждой куче ION
В Android 11 нет интерфейса для предоставления статистики по куче ION.
В следующей таблице сравниваются интерфейсы статистики 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 производился следующим образом:
 final long lostRAM = memInfo.getTotalSizeKb( ) - ( totalPss - totalSwapPss )
 - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
 — kernelUsed — memInfo.getZramTotalSizeKb() ;
 Компонент totalPss включал использование памяти графического процессора (возвращаемый интерфейсом Memtrack HAL getMemory() ). Компонент kernelUsed включал общее использование памяти DMA-BUF. Однако для устройств Android память графического процессора исходила из следующего:
- Прямые выделения, сделанные драйвером графического процессора с использованием физического распределителя страниц
- DMA-BUF отображаются в адресное пространство графического процессора
Таким образом, DMA-BUF, отображаемые в памяти в адресное пространство графического процессора, дважды вычитались при подсчете потерянной оперативной памяти. В Android 12 реализовано решение для расчета размера DMA-BUF, отображаемых в адресное пространство графического процессора, что означает, что он учитывается только один раз при расчете потерянной оперативной памяти.
Детали решения следующие:
-  Memtrack HAL API getMemory()при вызове с PID 0 должен сообщать глобальный общий объем частной памяти GPU для MemtrackType::GL и MemtrackRecord::FLAG_SMAPS_UNACCOUNTED.
-  getMemory() при вызове с PID0дляMemtrackType, отличного отGL, не должен завершаться ошибкой. Вместо этого он должен возвращать 0.
- Решение точки трассировки памяти графического процессора/eBPF , добавленное в Android 12, учитывает общую память графического процессора. Вычитание общей собственной памяти графического процессора из общей памяти графического процессора дает размер DMA-BUF, отображаемых в адресное пространство графического процессора. Затем это значение можно использовать для повышения точности расчетов потерянной оперативной памяти за счет правильного учета использования памяти графическим процессором.
-  Частная память графического процессора включена в totalPssв большинстве реализаций Memtrack HAL и поэтому должна быть дедуплицирована перед удалением ее изlostRAM.
Реализованное решение подробно описано в следующем разделе.
Удаление изменчивости Memtrack из потерянной оперативной памяти
 Поскольку реализации Memtrack HAL могут различаться у разных партнеров, память графического процессора, включенная в 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 и заменяется частной памятью графического процессора ( 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;
Обновленный расчет потерянной оперативной памяти
 Как общая частная память графического процессора, так и общая экспортируемая буферная память DMA содержатся в kernelUsed + totalPss , который удаляется из lostRAM . Это устраняет как двойной учет, так и изменчивость Memtrack при расчете потерянной оперативной памяти.
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 и памяти графического процессора. Реализуйте 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();
 Чтобы убедиться, что ваша версия работает должным образом, интегрируйте точки трассировки в драйверы графического процессора и реализуйте API-интерфейс AIDL memtrack HAL getMemory() , чтобы правильно возвращать глобальную общую личную память графического процессора при вызове с PID 0 для MemtrackType::GL и MemtrackRecord:: FLAG_SMAPS_UNACCOUNTED.
