Есть ли способ сжать память в андроиде, чтобы понизить верхнюю отметку? - PullRequest
9 голосов
/ 13 июля 2011

Обратите внимание, у меня нет утечки памяти.Мой вопрос касается более тонкой проблемы.

Я недавно написал приложение для Android, которое выполняет обработку изображений.Изображение загружается как растровое изображение, затем копируется в пиксели, обрабатывается таким образом, что использует много памяти (например, преобразования Фурье в представлениях с плавающей запятой и т. Д.), Затем преобразуется обратно в растровое изображение и сохраняется.

Проблема заключается в том, что, по крайней мере, в ОС Android 2.3 общее ограничение памяти (обычно 16 МБ) комбинируется с растровыми изображениями Java и (хранится извне), а максимальный уровень Java не снижается (что я могу различить), даже когда памятьсвободен (успешно GC'd), что означает, что когда я иду, чтобы выделить окончательный Bitmap, мне часто «не хватает памяти», хотя к этому моменту я освободил (и GC'd) большую часть пространства.Т.е. мне никогда не нужны полные 16 МБ сразу, но пространство, оставленное для растровых изображений, кажется, составляет 16 МБ минус использование исторической кучи Java MAX (в отличие от текущего использования).

Я наблюдал за техническим выступлением одного изразработчики Android по поводу проблем с памятью, и он подразумевал, что эта проблема была исправлена ​​в последующих версиях ОС (они переместили растровую память в пространство кучи Java), но в то же время большинство людей, желающих использовать мое приложение, используют 2.2 или 2.3.

Короче говоря, мне интересно, сжата ли когда-нибудь куча java (в сущности, не фрагментирована), чтобы высшая отметка уменьшилась (и если да, то как это сделать)?

Если нет, то есть у кого-нибудь еще предложение, как справиться с этой проблемой?

Ответы [ 3 ]

1 голос
/ 15 июля 2011

Пока что нет никаких признаков того, что существует какой-либо способ сжать память.

Вот мой обходной путь, который является неоптимальным, но намного лучше, чем прежнее поведение:

Теперь я намеренно придерживаюськ исходному растровому изображению, пока я выполняю свою обработку, а затем recycle () и обнуляем его, и GC (), но не раньше, чем непосредственно перед распределением моего выходного растрового изображения.

Что это делает, это резервный внешний (растровое изображение)) и заставить мое приложение исчерпать кучу Java (во время обработки, перед вызовом recycle ()), которую я могу по крайней мере поймать и обработать, повторив попытку на меньшем изображении.(Раньше все казалось нормальным, пока я не попытался сохранить, но к тому времени было уже слишком поздно и невозможно было восстановить.)

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

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

Имо, это серьезная ошибка в способе работы Android с битовой картой, но я считаю, что это исправлено в более новых версиях ОС, так что, надеюсь, я смогу отключить этот обходной путь при условиивыпуск ОС.

1 голос
/ 13 июля 2011

Короче говоря, мне интересно, если куча Java когда-либо уплотнялась (в сущности, не фрагментирована), чтобы высшая отметка уменьшалась (и если да, то как это сделать)?

Каким бы ни было его поведение, оно, безусловно, не находится под вашим контролем.

Если нет, то есть ли у кого-нибудь другое предложение, как решить эту проблему?

В идеале, использовать свое собственное Bitmaps.Вы не указываете, что на самом деле «обрабатывается так, что использует много памяти».Однако, если это не меняет размеры или битовую глубину изображения, скопируйте данные обратно в исходный Bitmap вместо выделения нового, если это возможно.

Обработка изображений в Android 2.x - одно из немногих мест, где я вижу оправдание использования нескольких процессов.Вы добавите накладные расходы для передачи данных изображения между процессами, но у другого процесса есть своя собственная куча (Java и нативная), так что это может дать вам больше «пространства локтя».

0 голосов
/ 13 июля 2011

Я предполагаю, что вы уже звоните Bitmap.recycle(), но это единственное, что я запомнил, а вы не говорили.

...