Кажется, что «AS» постороннее вблизи «AS TABLE_RESOLVERS»
Обратите внимание, что использование памяти в современных операционных системах, таких как Linux, является чрезвычайно сложной и трудной для понимания областью. На самом деле шансы, что вы действительно правильно интерпретируете полученные числа, крайне низки. (Практически каждый раз, когда я смотрю на цифры использования памяти с другими инженерами, всегда ведется долгая дискуссия о том, что они на самом деле означают, что приводит только к расплывчатым выводам.)
Примечание: теперь у нас есть гораздо более обширная документация по ] Управление памятью вашего приложения , который охватывает большую часть материала здесь и более актуален с учетом состояния Android.
Первым делом стоит, вероятно, прочитать последнюю часть этой статьи, в которой обсуждается, как управляется память в Android:
API службы меняются, начиная с Android 2.0
Сейчас ActivityManager.getMemoryInfo ()
- это наш API самого высокого уровня для просмотра общего использования памяти. В основном это помогает приложению оценить, насколько система приближается к тому, чтобы не иметь больше памяти для фоновых процессов, и, таким образом, необходимо начать убивать необходимые процессы, такие как службы. Для приложений, работающих только на Java, от этого мало толку, поскольку ограничение размера кучи Java отчасти используется для того, чтобы одно приложение не могло нагружать систему до этого момента.
Переходя на более низкий уровень, вы можете использовать Debug API для получения необработанной информации уровня ядра об использовании памяти: android.os.Debug.MemoryInfo
Примечание, начиная с версии 2.0, также существует API, ActivityManager.getProcessMemoryInfo
, чтобы получить эту информацию о другом процессе: ActivityManager.getProcessMemoryInfo (int [])
Это возвращает низкоуровневую структуру MemoryInfo со всеми этими данными:
/** The proportional set size for dalvik. */
public int dalvikPss;
/** The private dirty pages used by dalvik. */
public int dalvikPrivateDirty;
/** The shared dirty pages used by dalvik. */
public int dalvikSharedDirty;
/** The proportional set size for the native heap. */
public int nativePss;
/** The private dirty pages used by the native heap. */
public int nativePrivateDirty;
/** The shared dirty pages used by the native heap. */
public int nativeSharedDirty;
/** The proportional set size for everything else. */
public int otherPss;
/** The private dirty pages used by everything else. */
public int otherPrivateDirty;
/** The shared dirty pages used by everything else. */
public int otherSharedDirty;
Но что касается разницы между Pss
, PrivateDirty
, и SharedDirty
... ну а теперь самое интересное.
Большая часть памяти в Android (и Linux в целом) фактически распределяется между несколькими процессами. Так что, сколько памяти использует процесс, на самом деле неясно. Добавьте поверх этой подкачки на диск (не говоря уже о свопе, который мы не используем на Android), и это станет еще менее ясным.
Таким образом, если вы возьмете всю физическую оперативную память, фактически отображенную для каждого процесса, и сложите все процессы, вы, вероятно, получите число, намного превышающее фактический общий объем ОЗУ.
Число Pss
- это метрика, вычисляемая ядром, которая учитывает совместное использование памяти - в основном каждая страница ОЗУ в процессе масштабируется пропорционально количеству других процессов, также использующих эту страницу. Таким образом, вы можете (теоретически) сложить pss для всех процессов, чтобы увидеть общий объем оперативной памяти, которую они используют, и сравнить pss между процессами, чтобы получить приблизительное представление об их относительном весе.
Другой интересный показатель - PrivateDirty
, который, по сути, представляет собой объем ОЗУ внутри процесса, который не может быть выгружен на диск (он не поддерживается теми же данными на диске), и не является совместно с любыми другими процессами. Другой способ взглянуть на это - это оперативная память, которая станет доступной для системы, когда этот процесс завершится (и, вероятно, быстро попадет в кеши и другие способы ее использования).
Это почти все API SDK для этого. Однако вы как разработчик можете сделать со своим устройством больше.
Используя adb
, вы можете получить много информации об использовании памяти работающей системой. Распространенной является команда adb shell dumpsys meminfo
, которая выдаст кучу информации об использовании памяти каждым процессом Java, содержащую вышеупомянутую информацию, а также множество других вещей. Вы также можете указать имя или идентификатор отдельного процесса, чтобы увидеть, например adb shell dumpsys meminfo system
предоставьте мне системный процесс:
** MEMINFO in pid 890 [system] ** native dalvik other total size: 10940 7047 N/A 17987 allocated: 8943 5516 N/A 14459 free: 336 1531 N/A 1867 (Pss): 4585 9282 11916 25783 (shared dirty): 2184 3596 916 6696 (priv dirty): 4504 5956 7456 17916 Objects Views: 149 ViewRoots: 4 AppContexts: 13 Activities: 0 Assets: 4 AssetManagers: 4 Local Binders: 141 Proxy Binders: 158 Death Recipients: 49 OpenSSL Sockets: 0 SQL heap: 205 dbFiles: 0 numPagers: 0 inactivePageKB: 0 activePageKB: 0
Верхний раздел является основным, где размер
- это общий размер в адресном пространстве конкретной кучи, распределенный
- это фактическое выделение в килобайтах, которое куча считает, что у него есть, свободно
- это оставшийся свободный килобайт в куче для дополнительных выделений и pss
и priv dirty
такие же, как обсуждалось ранее, для страниц, связанных с каждой из куч.
Если вы просто хотите посмотреть на использование памяти всеми процессами, вы можете использовать команду adb shell procrank
. Результат этого в той же системе выглядит так:
PID Vss Rss Pss Uss cmdline 890 84456K 48668K 25850K 21284K system_server 1231 50748K 39088K 17587K 13792K com.android.launcher2 947 34488K 28528K 10834K 9308K com.android.wallpaper 987 26964K 26956K 8751K 7308K com.google.process.gapps 954 24300K 24296K 6249K 4824K com.android.phone 948 23020K 23016K 5864K 4748K com.android.inputmethod.latin 888 25728K 25724K 5774K 3668K zygote 977 24100K 24096K 5667K 4340K android.process.acore ... 59 336K 332K 99K 92K /system/bin/installd 60 396K 392K 93K 84K /system/bin/keystore 51 280K 276K 74K 68K /system/bin/servicemanager 54 256K 252K 69K 64K /system/bin/debuggerd
Здесь столбцы Vss
и Rss
в основном представляют собой шум (это прямое адресное пространство и использование ОЗУ процессом, где, если вы сложите использование ОЗУ между процессами, вы получите смехотворно большое число).
Pss
- это то, что мы видели ранее, а Uss
- Priv Dirty
.
Здесь следует отметить интересную вещь: Pss
и Uss
немного (или более чем немного) отличаются от того, что мы видели в meminfo
. Это почему?Ну, procrank использует другой механизм ядра для сбора данных, чем meminfo
, и они дают несколько другие результаты. Это почему? Честно говоря, я понятия не имею. Я считаю, что procrank
может быть более точным ... но на самом деле это просто оставляет суть: «относитесь к любой информации из памяти, которую вы получаете с долей скептицизма; часто с очень большой зернистостью».
Наконец, есть команда adb shell cat / proc / meminfo
, которая дает сводку об общем использовании памяти системой. Здесь много данных, только первые несколько цифр заслуживают обсуждения (а остальные понятны немногим, и мои вопросы к тем немногим людям о них часто приводят к противоречивым объяснениям):
MemTotal: 395144 kB MemFree: 184936 kB Buffers: 880 kB Cached: 84104 kB SwapCached: 0 kB
MemTotal
- это общий объем памяти, доступной ядру и пользовательскому пространству (часто меньше, чем фактическая физическая RAM устройства, поскольку часть этой RAM необходима для радио, буферов DMA и т. д.).
MemFree
- это объем ОЗУ, который вообще не используется. Число, которое вы видите здесь, очень велико; обычно в системе Android это всего несколько МБ, так как мы пытаемся использовать доступную память для поддержания работы процессов
Кэширование
- это ОЗУ, используемое для кэшей файловой системы и других подобных вещей. В обычных системах для этого потребуется около 20 МБ, чтобы избежать плохого состояния подкачки; Убийца нехватки памяти Android настроен для конкретной системы, чтобы гарантировать, что фоновые процессы завершаются до того, как кэшированная оперативная память будет использована ими слишком много, чтобы привести к такой подкачке страниц.
1) Думаю, что нет, по крайней мере, не из Java.
2)
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
MemoryInfo mi = new MemoryInfo();
activityManager.getMemoryInfo(mi);
Log.i("memory free", "" + mi.availMem);
Эта работа продолжается, но я не понимаю этого:
ActivityManager activityManager = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
Log.i(TAG, " memoryInfo.availMem " + memoryInfo.availMem + "\n" );
Log.i(TAG, " memoryInfo.lowMemory " + memoryInfo.lowMemory + "\n" );
Log.i(TAG, " memoryInfo.threshold " + memoryInfo.threshold + "\n" );
List<RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses();
Map<Integer, String> pidMap = new TreeMap<Integer, String>();
for (RunningAppProcessInfo runningAppProcessInfo : runningAppProcesses)
{
pidMap.put(runningAppProcessInfo.pid, runningAppProcessInfo.processName);
}
Collection<Integer> keys = pidMap.keySet();
for(int key : keys)
{
int pids[] = new int[1];
pids[0] = key;
android.os.Debug.MemoryInfo[] memoryInfoArray = activityManager.getProcessMemoryInfo(pids);
for(android.os.Debug.MemoryInfo pidMemoryInfo: memoryInfoArray)
{
Log.i(TAG, String.format("** MEMINFO in pid %d [%s] **\n",pids[0],pidMap.get(pids[0])));
Log.i(TAG, " pidMemoryInfo.getTotalPrivateDirty(): " + pidMemoryInfo.getTotalPrivateDirty() + "\n");
Log.i(TAG, " pidMemoryInfo.getTotalPss(): " + pidMemoryInfo.getTotalPss() + "\n");
Log.i(TAG, " pidMemoryInfo.getTotalSharedDirty(): " + pidMemoryInfo.getTotalSharedDirty() + "\n");
}
}
Почему PID не отображается на результат в activityManager.getProcessMemoryInfo ()? Очевидно, вы хотите сделать полученные данные значимыми, так почему же Google так усложнил корреляцию результатов? Текущая система даже не работает хорошо, если я хочу обработать все использование памяти, поскольку возвращаемый результат представляет собой массив объектов android.os.Debug.MemoryInfo, но ни один из этих объектов на самом деле не сообщает вам, с какими pid они связаны. Если вы просто передадите массив всех pid, у вас не будет возможности понять результаты. Насколько я понимаю, его использование делает бессмысленным передачу более чем одного pid за раз, а затем, если это так, зачем делать так, чтобы activityManager.getProcessMemoryInfo () принимал только массив int?