Как программно найти память, используемую в приложении Android?
Я надеюсь, что есть способ сделать это. Плюс, как мне получить свободную память телефона тоже?
java
android
memory
memory-management
Андреа Бакчега
источник
источник
Ответы:
Обратите внимание, что использование памяти в современных операционных системах, таких как Linux, является чрезвычайно сложной и трудной для понимания областью. На самом деле шансы на то, что вы на самом деле правильно интерпретируете полученные вами цифры, крайне низки. (Практически каждый раз, когда я смотрю на цифры использования памяти с другими инженерами, всегда идет долгая дискуссия о том, что они на самом деле означают, что приводит только к неопределенному выводу.)
Примечание: теперь у нас гораздо более обширная документация по управлению памятью вашего приложения, которая охватывает большую часть материала здесь и более соответствует состоянию Android.
Прежде всего, возможно, стоит прочитать последнюю часть этой статьи, в которой обсуждается, как управлять памятью в Android:
Изменения API сервиса, начиная с Android 2.0
Сейчас же
ActivityManager.getMemoryInfo()
это наш API верхнего уровня для оценки общего использования памяти. В основном это делается для того, чтобы помочь приложению определить, насколько близко система перестает иметь память для фоновых процессов, и, таким образом, нужно начинать убивать необходимые процессы, такие как службы. Для приложений на чистом Java это должно быть мало полезным, поскольку ограничение кучи Java отчасти позволяет избежать того, чтобы одно приложение могло нагружать систему до этого уровня.Переходя на более низкий уровень, вы можете использовать API отладки, чтобы получить необработанную информацию уровня ядра об использовании памяти: android.os.Debug.MemoryInfo
Обратите внимание, что начиная с 2.0 также существует API
ActivityManager.getProcessMemoryInfo
для получения этой информации о другом процессе: ActivityManager.getProcessMemoryInfo (int [])Это возвращает низкоуровневую структуру MemoryInfo со всеми этими данными:
Но , как к тому , что разница между
Pss
,PrivateDirty
иSharedDirty
... ну теперь начинается веселье.Большая часть памяти в Android (и системах Linux в целом) фактически распределяется между несколькими процессами. Итак, сколько памяти использует процесс, на самом деле не ясно. Добавьте поверх этого постраничного вывода на диск (не говоря уже об обмене, который мы не используем в Android), и это еще менее понятно.
Таким образом, если бы вы взяли всю физическую RAM, фактически сопоставленную каждому процессу, и суммировали все процессы, вы, вероятно, в конечном итоге получили бы число, намного превышающее фактическую общую RAM.
Pss
Число является метрикой ядра вычисляет , которая принимает во совместный счете памяти - в основном каждой страницу памяти в процессе масштабируется отношением числа других процессов , также используя эту страницу. Таким образом, вы можете (теоретически) сложить pss во всех процессах, чтобы увидеть общую оперативную память, которую они используют, и сравнить pss между процессами, чтобы получить приблизительное представление об их относительном весе.Другой интересный показатель здесь -
PrivateDirty
это объем оперативной памяти внутри процесса, который не может быть перенесен на диск (он не поддерживается теми же данными на диске) и не используется совместно с другими процессами. Еще один способ взглянуть на это - это оперативная память, которая станет доступной для системы, когда этот процесс завершится (и, вероятно, будет быстро отнесен к кэшам и другим видам ее использования).Это в значительной степени SDK API для этого. Тем не менее, вы можете сделать больше как разработчик своего устройства.
Используя
adb
, вы можете получить много информации об использовании памяти работающей системой. Распространенной является команда,adb shell dumpsys meminfo
которая будет выдавать кучу информации об использовании памяти каждым процессом Java, содержащую вышеупомянутую информацию, а также множество других вещей. Вы также можете указать имя или pid отдельного процесса, например,adb shell dumpsys meminfo system
дать мне системный процесс:Верхний раздел является основным, где
size
общий размер в адресном пространстве конкретной кучи,allocated
это килобайт фактических выделений, которые, как думает куча, он имеет,free
является ли оставшийся килобайт свободным в куче для дополнительных выделений,pss
иpriv dirty
они одинаковы. как обсуждалось ранее, специфично для страниц, связанных с каждой из куч.Если вы просто хотите посмотреть на использование памяти во всех процессах, вы можете использовать команду
adb shell procrank
. Вывод этого на той же системе выглядит так:Здесь
Vss
иRss
столбцы, в основном шум (это прямой вперед адресное пространство и использование памяти процесса, в котором , если вы складываете использование оперативной памяти между процессами вы получите невероятно большое количество).Pss
как мы видели раньше, иUss
естьPriv Dirty
.Интересная вещь, чтобы отметить здесь:
Pss
иUss
немного (или более чем немного) отличается от того, что мы видели вmeminfo
. Это почему? Что ж, procrank использует другой механизм ядра для сбора своих данныхmeminfo
, и они дают немного разные результаты. Это почему? Честно говоря, я понятия не имею. Я полагаю, чтоprocrank
может быть более точным ... но на самом деле, это просто оставляет смысл: «бери любую информацию о памяти, которую получаешь, с крошкой соли; часто с очень большой крошкой».Наконец, есть команда,
adb shell cat /proc/meminfo
которая дает сводную информацию об общем использовании памяти системой. Здесь много данных, только первые несколько цифр, которые стоит обсудить (а остальные понимают немногие, и мои вопросы о тех немногих людях о них часто приводят к противоречивым объяснениям):MemTotal
это общий объем памяти, доступной ядру и пользовательскому пространству (часто меньше, чем фактическая физическая память устройства, так как часть этой памяти необходима для радиосвязи, буферов DMA и т. д.).MemFree
это объем оперативной памяти, который не используется вообще. Число, которое вы видите здесь, очень высоко; как правило, в системе Android это будет всего лишь несколько МБ, так как мы стараемся использовать доступную память для поддержания процессов в рабочем состоянииCached
ОЗУ используется для кэшей файловой системы и других подобных вещей. Типичные системы должны иметь около 20 МБ или около того, чтобы избежать перехода в состояние плохой подкачки; Android out of memory killer настроен для конкретной системы, чтобы гарантировать, что фоновые процессы будут убиты до того, как кэшированная оперативная память израсходует ими слишком много, чтобы привести к такой подкачке.источник
Да, вы можете получить информацию о памяти программным путем и решить, следует ли выполнять объемную работу с памятью.
Получить размер кучи виртуальной машины можно по телефону:
Получить выделенную память виртуальной машины, позвонив:
Получить ограничение размера кучи виртуальной машины можно по телефону:
Получить собственную выделенную память, позвонив:
Я сделал приложение, чтобы выяснить поведение OutOfMemoryError и отслеживать использование памяти.
https://play.google.com/store/apps/details?id=net.coocood.oomresearch
Вы можете получить исходный код по адресу https://github.com/coocood/oom-research
источник
Это работа в процессе, но это то, что я не понимаю:
Почему PID не сопоставляется с результатом в activityManager.getProcessMemoryInfo ()? Очевидно, что вы хотите сделать полученные данные значимыми, так почему же Google так сложно сопоставить результаты? Текущая система даже не работает хорошо, если я хочу обработать все использование памяти, поскольку возвращаемый результат является массивом объектов android.os.Debug.MemoryInfo, но ни один из этих объектов фактически не говорит вам, с какими pids они связаны. Если вы просто передадите массив всех pids, у вас не будет возможности понять результаты. Насколько я понимаю, его использование делает бессмысленным передачу более одного pid за раз, а затем, если это так, зачем делать так, чтобы activityManager.getProcessMemoryInfo () принимает только массив int?
источник
Hackbod's - один из лучших ответов на переполнение стека. Это проливает свет на очень непонятный предмет. Это мне очень помогло.
Еще один действительно полезный ресурс - это видео, которое обязательно нужно посмотреть: Google I / O 2011: управление памятью для приложений Android
ОБНОВИТЬ:
Process Stats, сервис, позволяющий узнать, как ваше приложение управляет памятью, объясняется в посте блога. Process Stats: Понимание того, как ваше приложение использует оперативную память от Dianne Hackborn:
источник
Android Studio 0.8.10+ представила невероятно полезный инструмент под названием Memory Monitor .
Для чего это хорошо:
Рисунок 1. Принудительное событие GC (Сборка мусора) на Android Memory Monitor
Используя его, вы можете получить много полезной информации о потреблении оперативной памяти вашего приложения.
источник
1) Наверное, нет, по крайней мере, не с Java.
2)
источник
Мы выяснили, что у всех стандартных способов получения полной памяти текущего процесса есть некоторые проблемы.
Runtime.getRuntime().totalMemory()
: возвращает только память JVMActivityManager.getMemoryInfo()
,Process.getFreeMemory()
А все остальное основано на/proc/meminfo
- возвращает Информация о памяти обо всех процессах в сочетании (например , android_util_Process.cpp )Debug.getNativeHeapAllocatedSize()
- использует,mallinfo()
которые возвращают информацию о распределении памяти, выполняемой толькоmalloc()
и соответствующими функциями (см. android_os_Debug.cpp )Debug.getMemoryInfo()
- делает работу, но это слишком медленно. Требуется около 200 мс на Nexus 6 для одного звонка. Снижение производительности делает эту функцию бесполезной для нас, поскольку мы вызываем ее регулярно, и каждый вызов довольно заметен (см. Android_os_Debug.cpp )ActivityManager.getProcessMemoryInfo(int[])
- звонкиDebug.getMemoryInfo()
внутри (см. ActivityManagerService.java )Наконец, мы закончили с использованием следующего кода:
Возвращает метрику VmRSS . Вы можете найти более подробную информацию об этом здесь: один , два и три .
PS Я заметил, что в теме все еще отсутствует фактический и простой фрагмент кода о том, как оценить использование частной памяти процессом, если производительность не является критическим требованием:
источник
В Android Studio 3.0 они представили Android-Profiler, чтобы помочь вам понять, как ваше приложение использует ресурсы процессора, памяти, сети и батареи.
https://developer.android.com/studio/profile/android-profiler
источник
Выше приведено много ответов, которые определенно помогут вам, но (после 2 дней использования и изучения инструментов памяти adb) я думаю, что тоже могу помочь с моим мнением .
Как говорит Хэкбод: Таким образом, если бы вы взяли всю физическую RAM, фактически сопоставленную с каждым процессом, и суммировали все процессы, вы, вероятно, в итоге получили бы число, намного превышающее фактическую общую RAM. таким образом, вы не сможете получить точное количество памяти на процесс.
Но вы можете приблизиться к этому по некоторой логике .. и я расскажу, как ..
Итак, во-первых, вам нужно быть пользователем root, чтобы все заработало. Войдите в консоль с правами суперпользователя, выполнив
su
процесс, и получите егоoutput and input stream
. Затем передайтеid\n
(введите) в ouputstream и запишите его для обработки выходных данных. Если вы получите входной поток, содержащийuid=0
, вы являетесь пользователем root.Теперь вот логика, которую вы будете использовать в процессе выше
Когда вы получаете ouputstream процесса, передайте свою команду (procrank, dumpsys meminfo и т. Д.) С
\n
вместо id и получите егоinputstream
и прочитайте, сохраните поток в байтах [], char [] и т. Д. Используйте необработанные данные ... и вы сделаны!!!!!разрешение:
Проверьте, являетесь ли вы пользователем root:
Выполните вашу команду с
su
logcat:
Это всего лишь попытка, пожалуйста, предложите мне, если я что-то пропустил
источник