2014-12-21 3 views
-2

Для применения, что я работаю над эффективностью, очень важно. Чтобы избежать ненужной сборки мусора, я выделил много памяти (чтобы увеличить размер кучи) и сразу же выпустил ее. Однако, независимо от того, сколько свободной памяти у меня есть, сбор мусора все еще происходит.Странное поведение сборщика мусора Android

Когда я не делаю этого дополнительного выделения/освобождения памяти, у меня есть только 24% свободной памяти, по сравнению с 63% в журнале ниже, но количество вызовов GC одинаково. GC-паузы одинаковы. Время выполнения (программы) одинаково.

Может ли кто-нибудь объяснить это странное поведение GC? Почему GC_FOR_ALLOC запускается вообще? Существует тонна свободной памяти.

В моей программе основными операциями являются: чтение файлов, шифрование, передача данных. Для передачи данных и чтения файлов я использую ByteBuffer и FileChannel, SocketChannel. Может ли огромное количество распределений ByteBuffer быть узким местом? Кажется, что у меня нет утечек памяти.

Программа протестирована на GalaxyS3 (Android 4.4.2) и GalaxyS2 (Android 4.1.2)

12-21 00:30:54.973: I/dalvikvm-heap(30222): Grow heap (frag case) to 44.361MB for 25000016-byte  allocation 
12-21 00:30:55.463: D/dalvikvm(30222): GC_FOR_ALLOC freed 43K, 8% free 42893K/46416K, paused 20ms, total 20ms 
12-21 00:31:01.900: D/dalvikvm(30222): GC_FOR_ALLOC freed 28367K, 63% free 18615K/49480K, paused 39ms, total 39ms 
12-21 00:31:07.606: D/dalvikvm(30222): GC_FOR_ALLOC freed 3600K, 63% free 18648K/49480K, paused 42ms, total 42ms 
12-21 00:31:12.151: D/dalvikvm(30222): GC_FOR_ALLOC freed 3640K, 63% free 18652K/49480K, paused 48ms, total 48ms 
12-21 00:31:17.757: D/dalvikvm(30222): GC_FOR_ALLOC freed 3627K, 63% free 18669K/49480K, paused 93ms, total 93ms 
12-21 00:31:24.014: D/dalvikvm(30222): GC_FOR_ALLOC freed 3641K, 63% free 18679K/49480K, paused 46ms, total 46ms 
12-21 00:31:30.090: D/dalvikvm(30222): GC_FOR_ALLOC freed 3644K, 63% free 18688K/49480K, paused 48ms, total 48ms 
12-21 00:31:35.536: D/dalvikvm(30222): GC_FOR_ALLOC freed 3639K, 63% free 18706K/49480K, paused 50ms, total 50ms 
12-21 00:31:41.763: D/dalvikvm(30222): GC_FOR_ALLOC freed 3659K, 63% free 18711K/49480K, paused 52ms, total 53ms 
12-21 00:31:47.439: D/dalvikvm(30222): GC_FOR_ALLOC freed 3652K, 63% free 18724K/49480K, paused 54ms, total 54ms 
12-21 00:31:53.085: D/dalvikvm(30222): GC_FOR_ALLOC freed 3677K, 63% free 18716K/49480K, paused 38ms, total 38ms 
12-21 00:31:59.882: D/dalvikvm(30222): GC_FOR_ALLOC freed 3672K, 63% free 18711K/49480K, paused 50ms, total 67ms 
12-21 00:32:05.838: D/dalvikvm(30222): GC_FOR_ALLOC freed 3672K, 63% free 18704K/49480K, paused 42ms, total 42ms 
12-21 00:32:13.276: D/dalvikvm(30222): GC_FOR_ALLOC freed 3680K, 63% free 18686K/49480K, paused 37ms, total 37ms 

P.S. Код очень длинный, поэтому я не могу его публиковать.

Благодарим вас за помощь, подсказку или догадки.

+3

Это не мусорная коллекция, которая здесь странная; это поведение вашего приложения –

+0

@AndrewBarber Что не так с поведением приложения? Почему это не GC? –

+2

Ваш первый абзац. Это не то, как обычно будет вести себя приложение. Вы также не понимаете, как работает сборщик мусора, или почему. Свободная память не так важна, как вы думаете. –

ответ

1

Почему GC_FOR_ALLOC запускается вообще? Существует тонна свободной памяти.

myself Цитирование:

в JVM есть одна вещь, что Dalvik VM не делает: уплотн сборщик мусора.

Когда мы пишем программы на языке, запущенном во время выполнения поддержки коллекции мусора, мы создаем кучу объектов, и позже мы выпускаем некоторые подмножества этих объектов. Остальные мы удерживаем на некоторое время, потому что мы все еще используем их. В Android, например, наш Application, наш ContentProviders, наши Threads, наши собственные статические члены данных и т. Д. Будут жить в течение некоторого времени, во многих случаях на протяжении всего процесса. Все, что они могут достичь, также не получит сбор мусора. Таким образом, мы выделяем кучу памяти и выпускаем часть этой памяти по мере запуска нашего приложения.

С уплотняющим сборщиком мусора в памяти накопились долгоживущие объекты, чтобы объединить освобожденные блоки памяти. Сеть состоит в том, что все свободное пространство кучи должно быть доступно как один непрерывный блок, подходящий для распределения.

(детали являются более сложными, чем это, но это сообщение в блоге, не диссертация)

С без уплотняющей сборщика мусора, ничего не скользит вокруг в памяти. Мы завершаем фрагментацию кучи, поскольку то, что когда-то было первозданной 16-мегабайтной (или 32 МБ, или 48 МБ или что-то еще) кучей, теперь представляет собой кучу объектов с перемежающейся свободной памятью. Несмотря на то, что у нас может быть 10 МБ свободного пространства кучи, если самый большой отдельный блок этого свободного кучного пространства составляет всего 1 МБ, мы не можем выделить битмап 8 МБ, потому что свободного блока недостаточно.

Dalvik VM имеет сборщик мусора, не содержащий уплотнения.

Ваших GC_FOR_ALLOC линий предполагает, что вы делаете распределения, для которых нет свободного смежного большого достаточно блока в момент выделения, заставляя Dalvik, чтобы пройти через GC, чтобы попытаться освободить память таким образом, что вам завершайте с достаточно большим блоком.

Если вы хотите уменьшить или удалить ваши линии GC_FOR_ALLOC, вам нужно будет попытаться определить, какие ваши большие ассигнования. Здесь «большой» относится к отдельным распределениям, поэтому очень сложный графа объектов может быть «большим» в целом, но каждый отдельный объект является небольшим, и поэтому это не проблема. byte[] Атрибуты, как правило, являются виновниками, по крайней мере, для приложений с битовым перебором.

+0

Большое спасибо за объяснение. В моей реализации я выделяю огромное количество маленьких объектов. Вероятно, они путают кучу –

Смежные вопросы