При исследовании использования памяти начните с инструментов высокоуровневой оценки, чтобы определить, какие категории памяти являются наиболее значимыми.
dumpsys meminfo
Наиболее распространенный способ получить общее представление об использовании памяти приложением — это dumpsys meminfo . Для получения подробной информации, включая все сопоставления памяти, часто полезно добавить флаг -a :
adb shell dumpsys meminfo -a <package_name_or_pid>
Вот пример выходных данных приложения, испытывающего нехватку памяти (обратите внимание на высокое значение SwapPss):
** MEMINFO in pid 4562 [com.android.memorylab] **
Pss Private Private SwapPss Rss Heap Heap Heap
Total Dirty Clean Dirty Total Size Alloc Free
------ ------ ------ ------ ------ ------ ------ ------
Native Heap 394 268 64 17440 4264 29416 18128 8040
Dalvik Heap 165 8 0 672 8196 40949 32757 8192
Dalvik Other 47 28 0 604 1132
Stack 112 108 4 312 120
...
TOTAL 33197 580 788 21920 167776 70365 50885 16232
App Summary
Pss(KB) Rss(KB)
------ ------
Java Heap: 12 32608
Native Heap: 268 4264
Code: 724 125672
Stack: 108 120
Graphics: 0 0
Private Other: 256
System: 31829
Unknown: 5112
TOTAL PSS: 33197 TOTAL RSS: 167776 TOTAL SWAP PSS: 21920
Objects
Views: 15 ViewRootImpl: 1
AppContexts: 5 Activities: 1
...
Интерпретация данных
- Pss Total : Пропорциональный размер набора. Это сумма
Private Dirty-
Private Clean+ доля памяти, используемая вашим процессом совместно с другими процессами (например, образом загрузки Zygote). Это лучший показатель того, "за какой объем памяти отвечает это приложение".
-
- Private Dirty : Это оперативная память, используемая только вашим процессом и подвергнутая модификациям (или анонимная память). Это наиболее важный показатель для обнаружения утечек, поскольку эту память невозможно удалить.
- Private Clean : Память, используемая только вашим процессом, но представляющая собой неизмененную копию файла на хранилище (например, DEX-файла). Она может быть сброшена операционной системой при нехватке памяти.
- SwapPss : Память, которая была сжата и выгружена в ZRAM. Это может произойти либо из-за нехватки памяти в системе, либо потому, что среда выполнения Android определила фоновые процессы для сжатия (перемещения их неиспользуемых или неактивных страниц в ZRAM). В примере
dumpsysпочти всяNative HeapиDalvik Heapбыли перемещены в ZRAM.
- Краткое описание приложения : Категоризация более высокого уровня, объединяющая подробные строки в понятные категории.
- Объекты : Полезно для отслеживания утечек экземпляров
ActivitiesиViewRootImpl. Если вы выйдете из приложения и принудительно выполните сборку мусора, счетчикActivitiesдолжен вернуться к нулю.
Практическое упражнение: быстрая сортировка запросов с помощью meminfo.
В этом упражнении показано, как различные типы выделения памяти отображаются в meminfo .
Запустите приложение :
adb shell am start -W -n com.android.memorylab/.MainActivityПроверьте базовый уровень памяти :
adb shell dumpsys meminfo -s com.android.memorylab(Флаг
-sпредоставляет краткое и лаконичное описание категорий памяти).Выделить память Java : Нажмите кнопку «Выделить память Java (10 МБ)» 3 раза в приложении.
Обратите внимание на изменение : снова запустите
meminfo -s. Вы должны увидеть, что значение Java Heap увеличилось примерно на 30 000 КБ (30 МБ).Выделить собственную память : Нажмите один раз кнопку « Выделить собственную память (1 ГБ несжимаемой памяти)» .
Обратите внимание на изменение : снова запустите
meminfo -s. Значение Native Heap теперь должно значительно увеличиться (~1 000 000 КБ).
Глобальный обзор
Чтобы просмотреть использование памяти во всей системе, выполните следующую команду:
adb shell dumpsys meminfo
Здесь представлена сводка об использовании оперативной памяти, включая общий объем оперативной памяти, свободную оперативную память и список процессов, отсортированных по PSS.
Ключевые системные показатели
- ZRAM : Сжатый файл подкачки в оперативной памяти.
- DMA-BUF : Графические и разделяемые буферы памяти. Современные версии Android активно используют DMA-BUF для отрисовки пользовательского интерфейса. Если общий объем
DMA-BUFочень велик, проверьте процессы, интенсивно использующие графику, с помощью/sys/kernel/debug/dma_buf/bufinfo. - Потерянная оперативная память : память, которая не учитывается ядром или каким-либо процессом (например, аппаратно зарезервированные области).
показать карту
Для получения более подробной информации о расположении объектов в памяти процесса используйте showmap . Этот инструмент считывает данные из файла /proc/<pid>/smaps .
adb shell showmap <pid>
showmap выводит список всех отображений памяти в процессе. Ключевые отображения, на которые следует обратить внимание, включают:
-
[anon:scudo:primary]или[anon:libc_malloc]: собственный объем памяти кучи. В современных версиях Android используется распределитель памяти Scudo. -
*.art: Образы кучи Java (например, образ загрузки). -
[anon:dalvik-main space]: Основная куча Java. -
*.so: Разделяемые библиотеки. -
*.{oat,dex,odex,vdex}: Скомпилированный DEX-код.
Вы можете отсортировать выходные данные, чтобы найти пользователей, потребляющих больше всего частной памяти:
# Sort by private clean + private dirty memory
adb shell showmap <pid> | awk '{print $6+$7, $0}' | sort -rn | head -n 10
Пример выходных данных:
virtual shared shared private private Anon Shmem File Shared Private
size RSS PSS clean dirty clean dirty swap swapPSS HugePages PmdMapped PmdMapped Hugetlb Hugetlb Locked # object
-------- -------- -------- -------- -------- -------- -------- -------- -------- --------- --------- --------- -------- -------- -------- ---- ------------------------------
2776 18176 5784 2823 0 3008 308 2468 4700 4700 0 0 0 0 0 0 47 [anon:scudo:primary]
560 952 876 657 316 0 560 0 12 12 0 0 0 0 0 0 8 /data/app/.../base.apk
448 393216 448 448 0 0 0 448 0 0 0 0 0 0 0 0 2 [anon:dalvik-main space]
...
Практическое упражнение: углубленное изучение с помощью Showmap.
Узнайте, как определять конкретные сопоставления памяти и различать чистую и загрязненную память.
- Mmap Clean Memory : Нажмите один раз кнопку Mmap Clean Anon Memory (10MB) в приложении MemoryLab.
Получение идентификатора процесса (PID) : пользовательский интерфейс приложения отображает его PID. Вы также можете найти его с помощью этой команды:
adb shell pidof com.android.memorylabПроверить с помощью команды showmap :
# Replace <PID> with the actual process ID from the previous step adb shell showmap <PID> | grep "memorylab-clean"Определите отображение : вы должны увидеть анонимное отображение с меткой
[anon:memorylab-clean]и виртуальным размером ровно 10240 КБ. Обратите внимание, что значение параметра «dirty» для этого отображения, скорее всего, равно 0. Это «чистая» анонимная память, потому что мы использовалиmmapдля резервирования виртуального пространства, но еще не записывали в него данные (поэтому физическая оперативная память фактически не используется).Сравнение с нативной кучей : сравните это с отображениями
[anon:scudo:primary], которые появились бы вshowmap, если бы вы запустили его после шага 5 упражненияmeminfo. Поскольку этот нативный объем в 1 ГБ фактически записывает данные на каждую страницу, эти страницы являются «грязными» и будут часто отображаться в столбце «грязные частные ».Полезный совет (для больших объектов) : Обратите внимание на выделение памяти в куче Java из упражнения
meminfo. Поскольку это массивы размером 10 МБ, они, вероятно, отображаются вshowmapкак[anon:dalvik-free list large object space]. Среда выполнения Android (ART) помещает объекты размером более 12 КБ в отдельное пространство больших объектов (LOS), чтобы избежать фрагментации в основной куче.
procstats
В то время как meminfo предоставляет моментальный снимок состояния, procstats предоставляет исторические данные, периодически отслеживая состояние и использование памяти всех запущенных приложений. Это основной инструмент, используемый для долгосрочного мониторинга состояния памяти, и именно он отвечает за отображение отчетов об использовании памяти в настройках Android.
# View stats for the last 3 hours
adb shell dumpsys procstats --hours 3
Понимание штатов
Вывод procstats может быть очень объёмным. Наиболее важная часть — это метрики в скобках рядом с состоянием каждого процесса:
Top: 100% (54MB-64MB-67MB / 49MB-58MB-61MB / 110MB-120MB-130MB over 4)
Формат: (% времени в состоянии) (minPss-avgPss-maxPss / minUss-avgUss-maxUss / minRss-avgRss-maxRss по сэмплам)
- PSS (Proportional Set Size) : Общая память распределяется между процессами пропорционально.
- Uss (Unique Set Size) : Память, используемая только этим процессом (эквивалентно Private Clean + Private Dirty).
- RSS (Resident Set Size) : Общий объем используемой физической памяти, включая все разделяемые страницы (имеет тенденцию к завышению).
Почему это важно:
- В стабильном режиме работы приложения : значения min/avg/max близки друг к другу.
- Утечка памяти : максимальное значение значительно выше минимального, а среднее значение постепенно увеличивается со временем по мере роста количества выборок.
- Неравномерное использование : максимальное значение значительно выше среднего, что указывает на кратковременные ресурсоемкие операции (например, обработку изображений), которые могут привести к ошибке нехватки памяти, если выполняются в неподходящее время.
Состояния процесса
procstats отслеживает приложения в нескольких штатах (часто с сокращенным обозначением):
- Persist : Критические системные процессы, которые работают постоянно.
- Вверху : приложение в данный момент находится на переднем плане и видно пользователю.
- ImpFg (Important Foreground): Критические фоновые процессы (например, IME) или приложения с фоновой службой.
- ImpBg (Важные фоновые процессы): Фоновые процессы, которые считаются важными для системы.
- Fgs / BFgs : службы переднего плана или связанные службы переднего плана.
- Service / ServRst : Фоновые службы или службы, которые в данный момент перезапускаются.
- Cached / LastAct : Приложения, которые кэшируются в фоновом режиме для быстрого перезапуска. Системе безопасно завершить их работу.
Состояние памяти устройства и статистика времени выполнения
procstats также отслеживает, сколько времени всё устройство провело под нагрузкой памяти. Обратите внимание на раздел «Статистика выполнения» :
Run time Stats:
SOff/Norm: +1h10m15s
SOn/Norm: +15m20s
Low: +2m10s
Crit: +45s
- SOff / SOn : Экран выключен против экрана включен.
- Нормальный / Умеренный / Низкий / Критический : Уровни нагрузки на память (Нормальный, Умеренный, Низкий, Критический).
Если устройство проводит значительное время в режимах низкой или критической нагрузки, оно будет работать медленно, поскольку ядро активно освобождает память, а механизм завершения фоновых процессов (LMK) начинает завершать работу фоновых процессов. Затем вы можете просмотреть статистику по каждому пакету, чтобы увидеть, какие приложения используют много памяти именно тогда, когда устройство находится в этих стрессовых состояниях.
← Концепции | ↑ Вверх | Java →