- Большие требования к памяти в Android – что делать?
- Для начала немного теории
- Анализ памяти кучи
- Утечки памяти
- Высвобождайте память в ответ на события
- Большая куча
- Проверка, сколько памяти сможет использовать ваше приложение
- Используйте оптимизированные структуры данных
- Предотвращайте перемешивание памяти
- Телефон без тормозов: как значительно ускорить работу смартфона
Большие требования к памяти в Android – что делать?
Здравствуйте, уважаемые читатели.
Сегодня предлагаем вашему вниманию небольшой материал о грамотном использовании памяти в Android.
Приятного чтения!
Эта статья посвящена базовым приемам управления использованием памяти в приложениях – например, в браузерах, фоторедакторах и программах для просмотра PDF – в которых предъявляются большие запросы к памяти.
Для начала немного теории
Большинство приложений для Android работают поверх среды исполнения (ART), заменившей ныне устаревающую виртуальную машину Dalvik. ART и Dalvik похожи на виртуальную машину Java (JVM), с которой их роднят схожие принципы проектирования. Они используют для хранения данных приложений два отдельных пространства: стек и кучу.
Стек-память в Java используется для хранения локальных переменных (примитивных типов и ссылок на объекты). Каждый поток Java имеет собственный отдельный стек. Стек-память относительно невелика по сравнению с памятью кучи. Размер стека Java в Dalvik обычно составляет 32 KB для кода Java и 1 MB для нативного кода (C++/JNI). В ART появился унифицированный стек для Java и C++, размер которого составляет около 1 MB.
Когда приложение выбирает всю стек-память до предела, выдается ошибка StackOverflowError . Наиболее вероятные причины, по которым может быть достигнут предел стека – либо бесконечная рекурсия, либо чрезмерно глубокий вызов метода. Ссылки на стек-память всегда делаются в очередности LIFO (последним пришел – первым обслужен). Всякий раз при вызове метода в стек проталкивается новый фрейм с локальными переменными этого метода. Когда метод завершит работу, его фрейм выталкивается из стека, и любое возможное результирующее значение отправляется обратно в стек. Итак, первая проблема (бесконечная рекурсия) – это баг, который легко исправить, но вторая требует некоторого рефакторинга, заключающегося в разворачивании рекурсивных вызовов метода и преобразования их в цикл.
Память кучи в Java используется виртуальной машиной для выделения объектов. Когда бы ни создавался объект, это происходит в куче. Виртуальные машины, например, JVM или ART, выполняют регулярную сборку мусора, убирают все объекты, на которые больше не осталось ссылок, и таким образом высвобождают память для выделения новых объектов.
Для обеспечения удобства использования Android жестко ограничивает размеры кучи для каждого работающего приложения. Предельный размер кучи варьируется от устройства к устройству и зависит от того, сколько RAM на этом устройстве. Если ваше приложение достигает предельного размера кучи и пытается выделить еще памяти, то выдается ошибка OutOfMemoryError , и приложение завершается. Давайте рассмотрим некоторые примеры, помогающие избежать такой ситуации.
Анализ памяти кучи
Самый важный инструмент, позволяющий разобраться с проблемами памяти в ваших приложениях и понять, как используется память – это профилировщик памяти, доступный в Android Studio.
Этот инструмент визуализирует, сколько памяти потребляет ваше приложение с течением времени. Можно делать мгновенные снимки кучи Java в работающем приложении, записывать операции выделения памяти и следить за кучей или этой хронологией выделений памяти в мощном UI.
Типичный сеанс работы с профилировщиком памяти должен выглядеть так:
- Отсматриваем наиболее частые выделения памяти и проходы сборщика мусора для выявления возможных проблем с производительностью.
- Отсматриваем, как использовалась память с течением времени, в особенности такие операции, на которые, как известно, требуется выделять много памяти. Убедитесь, что после завершения этих операций использование памяти снижается. Например, ниже показано, как воздействует на память активность PdfActivity из PSPDFKit после загрузки документа.
- Делаем дамп кучи в разные моменты времени исполнения вашего приложения и проверяем, как используется память. Ищем большие объекты, которые хранятся в памяти и не подпадают под сборку мусора. Дампы кучи также помогают выявить утечки памяти – например, можно поискать в дампе кучи ваши активности и посмотреть, были ли собраны их старые экземпляры.
Утечки памяти
Современные сборщики мусора – это сложные произведения технологического искусства, результат многолетних исследований и разработок, в которых участвовали сотни людей, от академиков до разработчиков-профессионалов. Однако до сих пор приходится быть начеку, чтобы не допускать утечек в памяти.
Образцовое решение для выявления утечек в памяти – библиотека LeakCanary. Она автоматически выдает уведомления, когда в вашей тестовой сборке (development build), выдавая вам стектрейс утечки в UI этой программы. Можно (и следует) интегрировать ее уже сегодня, тем более, что это не сложно!
Особенно легко спровоцировать утечки памяти, работая со сложными жизненными циклами активностей или фрагментов Android. Такое часто случается в тех точках, где разработчики удерживают сильные ссылки на контексты UI или другие UI-специфичные объекты в фоновой задаче или в статических переменных. Один из способов спровоцировать такие задержки – активно покрутить устройство, когда тестируете ваше приложение.
Высвобождайте память в ответ на события
Android может затребовать у приложения выделенную память или просто принудительно завершить его, когда память необходимо высвободить для выполнения более критичных задач. Прежде, чем это произойдет, система позволит вам отдать всю память, которая вам не нужна. В вашей активности понадобится реализовать интерфейс ComponentCallbacks2 . В таком случае, всякий раз, когда ваша система будет испытывать дефицит памяти, поступит вызов к вашему методу onTrimMemory() , и вы сможете высвободить память или отключить те возможности, которые не будут работать в таких условиях дефицита памяти.
Так, подобные обратные вызовы обрабатываются в приложении PSPDFKit. Приложение PSPDFKit проектировалось с расчетом активного использования памяти для кэширования, чтобы работа с приложением шла как можно более гладко. Исходно неизвестно, сколько памяти доступно на устройстве, поэтому PSPDFKit адаптируется к ситуации и ограничивает использование памяти, когда получает уведомления о том, что памяти недостаточно. Поэтому приложения, интегрированные с PSPDFKit, работают даже на низкотехнологичных устройствах, но со сниженной производительностью из-за того, что кэширование отключено.
Большая куча
Одно из лобовых решений, позволяющих справиться с высокими требованиями к памяти – запросить большую кучу Dalvik для вашего приложения. Для этого можно добавить android:largeHeap=»true» к тегу в файле AndroidManifest.xml .
Если для свойства largeHeap задано значение true , Android будет создавать все процессы для вашего приложения с большой кучей. Эта настройка предназначена только для тех приложений, которые по природе своей без нее работать не смогут, то есть, они используют объемные ресурсы, которые должны одновременно умещаться в памяти.
Настоятельно не рекомендуется использовать большую кучу, если тем самым вы хотите только поднять потолок возможного использования памяти. Использование памяти всегда нужно оптимизировать, поскольку даже большой кучи вашему приложению может не хватить при работе на слабом устройстве с небольшой памятью.
Проверка, сколько памяти сможет использовать ваше приложение
Никогда не помешает проверить, насколько велика куча вашего приложения и динамически адаптировать ваш код и доступные возможности под эти пределы памяти. Можно прямо во время исполнения проверить максимальный размер кучи при помощи методов getMemoryClass() или getLargeMemoryClass() (когда включена большая куча).
Android поддерживает даже такие устройства, на которых всего 512 MB RAM. Убедитесь, что не обошли вниманием и низкотехнологичные устройства! При помощи метода isLowRamDevice() можно проверить, не запущено ли ваше приложение на таком устройстве, где мало доступной памяти. Точное поведение этого метода зависит от устройства, но обычно он возвращает true на тех устройствах, где меньше 1 GB RAM. Нужно убедиться, что ваше приложение корректно работает и на этих устройствах, и на них отключать все возможности, использующие большой объем памяти.
Подробнее о том, как Android работает на устройствах с малым объемом памяти, можно почитать здесь; здесь же даются дополнительные советы по оптимизации.
Используйте оптимизированные структуры данных
Во многих случаях приложения используют слишком много памяти по той простой причине, что для них используются не самые подходящие структуры данных.
Коллекции Java не могут хранить эффективные примитивные типы и требуют упаковки их ключей и значений. Например, HashMap с целочисленными ключами следует заменять оптимизированным SparseArray . В конечном итоге, вместо коллекций всегда можно использовать сырые массивы, и это отличная идея, если ваша коллекция не поддается изменению размера.
К другим структурам данных, неэффективным с точки зрения использования памяти, относятся различные сериализации. Да, действительно, форматы XML или JSON удобны в использовании, можно сократить использование памяти, если работать с более эффективным двоичным форматом, например, буферами протоколов.
Все эти примеры с упоминанием структур данных, оптимизированных для экономии памяти – просто подсказки. Как и в случае с рефакторингом, нужно сначала найти источник проблем, а затем переходить к таким оптимизациям производительности.
Предотвращайте перемешивание памяти
Виртуальные машины Java/Android выделяют объекты очень быстро. Сборка мусора также идет весьма быстро. Однако при выделении большого количества объектов за короткий промежуток времени можно столкнуться с проблемой под названием «перемешивание памяти» (memory churn). В таком случае виртуальная машина не будет успевать выделять объекты в таком темпе, а сборщик мусора – их утилизировать, и приложение начнет притормаживать, а в экстремальных случаях даже израсходует всю память.
Основная проблема на территории Android в данном случае такова, что мы не контролируем, когда будет происходить сборка мусора. Потенциально это может приводить к проблемам: например, сборщик мусора работает именно в то время, пока на экране разворачивается анимация, и мы превышаем порог в 16 мс, обеспечивающий гладкое отображение кадров. Поэтому важно предотвращать чрезмерно активное выделение памяти в коде.
Пример ситуации, приводящей к перемешиванию памяти – выделение больших объектов, например, Paint внутри метода onDraw() представления. В таком случае быстро создается много объектов, и может начаться сборка мусора, которая может негативно повлиять на работу этого представления. Как указывалось выше, всегда нужно отслеживать использование памяти, чтобы избегать таких ситуаций.
Источник
Телефон без тормозов: как значительно ускорить работу смартфона
Наверное, каждому знакома ситуация, когда спустя недолгое время после покупки смартфон начинает работать заметно медленнее. Чаще всего от этого страдают наши родители и дети, которым мы по “наследству” передаем свои старые устройства. Сегодня мы рассмотрим несколько наиболее эффективных решений данной проблемы: от самых простых до в меру продвинутых действий.
И хотя все “иллюстрации” будут приведены для Android, но в большинстве своем все они актуальны и для других мобильных операционных систем.
Освобождаем место для системы
Для начала обратите внимание на то, сколько у вашего телефона осталось свободной памяти. Это можно сделать, зайдя в «Настройки» и там перейдя в «Хранилище». Для корректной работы системы необходимо иметь небольшой запас дискового хранилища. Если же места нет, то система пытается его выделить, освобождая свои резервы. А на это уходит то самое дополнительное время, которое мы с вами и наблюдаем, как «тормоза». Я рекомендую следить, чтобы было свободно не менее 5 Гб памяти. Чем больше, тем лучше.
Здесь мы встречаемся с первой важной проблемой, где же это место найти. Ведь все в нашем телефоне нам нужно.
Помогая ускорить работу устройств своим родителям и знакомым, я заметил много абсолютно одинаковых фотографий, сделанных «на всякий случай». Иногда бывают видеоролики, которые нужны были в моменте, а теперь просто лежат пустым грузом. Благодаря таким файлам можно высвободить иногда даже очень внушительное по объему пространство.
Ну и не забываем о возможности перекинуть данные в облако или на внешний хранитель (карту памяти, флешку или жесткий диск).
После этих действий, зачастую сразу видно, что система стала меньше «задумываться» при запуске приложений и переключении между ними.
Следующим шагом имеет смысл удалить те приложения, которыми вы не пользовались как минимум 3 недели. Память под приложения в системе имеет строго ограниченный объем, который не зависит от оставшегося места на диске. То есть бывает такое, что памяти вроде еще много, а в вверху горит значок о том, что все место кончилось. В этом случае лучше какие-нибудь программы удалить.
Здесь будьте внимательны! Удалять нужно само приложение, а не иконку на заглавном экране (проверить это можно через меню «Настройки» — «Приложения»).
Бывает и такое, что некоторые программы удалить нельзя в принципе. Тогда постарайтесь их хотя бы “отключить”. Эту функцию они сами предлагают вместо удаления.
Режим энергосбережения
Обратите особое внимание и на то, чтобы режим энергосбережения был отключен либо установлен как «оптимальный». Это также может дать заметный прирост в скорости. В попытках продлить работку аккумулятора, система может искусственно занижать частоту работы процессора. В нашем случае — это абсолютно лишнее.
Виджеты
Значительную нагрузку на систему оказывают также установленные на заглавном экране виджеты (такие как погода, курс доллара, новости и всякое другое). С ними, конечно, красиво и очень наглядно, но за это приходится платить откликом операционной системы. Например курсы валют мы смотрим не чаще раза в день, а новости вообще можно вызвать на экран в тот момент, когда у нас на них есть время.
Обычно я рекомендую отключить все, что вы используете менее раза в день. А потом, при необходимости, можно вернуть, если что-то вдруг понадобилось.
Очищаем кэш браузера и системы
Для продвинутых пользователей я лично рекомендую очистить кэш браузера и системы. Кэш это информация, которая загружается на ваш смартфон, например, при открытии любого сайта. По ходу использования такая информация копится и может достигать нескольких гигабайт. При этом никакой полезной работы вся эта куча не делает. По факту — это просто мусор, который надо время от времени вычищать.
Для начала выполним очистку в браузере. Для этого в настройках перейдем – «История» — «Очистить историю» и там нажать “Удалить данные”. За непосредственно кэш отвечает третья галочка сверху.
У приложений тоже скапливается подобный мусор, но его очистить немного сложнее. Например, в телефонах Xiaomi нужно зайти в раздел «Хранилище» — «Данные кэша» и согласится на его очистку. У других производителей для этих целей имеются специальные, вшитые в систему программы. У Самсунг, например, это «Обслуживание устройства», а у менее известных брендов «Менеджер хранилища».
Также эту функцию можно осуществить из системного меню, зажав при старте аппарата громкость вверх и кнопку включения. Там нужно войти в меню «Recovery» и выполнить функцию «Wipe Cache» и выбрать «Yes». Больше там ничего там не трогайте!
Еще один способ очистки
Эти же действия можно осуществить и установив специальные приложения из Play Market, например, «One Booster», «Booster Master» и «Ant Booster». Подобных приложений целая куча.
Однако, через системные функции будет намного надежнее. После оптимизации обязательно удалите все эти “бустеры”, так как ресурсы они жрут будь здоров. То есть, установили — почистили- удалили.
Промежуточные итоги
Так мы очистили место в общей памяти, удалили ненужные приложения и виджеты и почистили кэш. Этих действий уже достаточно, чтобы на собственном опыте ощутить значительный прирост скорости работы смартфона.
Данная процедура лично у меня занимает от 3 до 5 минут, после чего даже старенькие телефоны родителей начинают “бегать” заметно шустрее.
Далее рекомендуется выключить и включить телефон снова. Обратите внимание! Не перезагрузить, а именно выключить, а затем включить. Это очень разные процессы и только полное отключение позволяет очистить служебные области памяти.
Визуальное обнаружение «тяжелых» программ
Не менее полезно будет войти в настройки аккумулятора обратить внимание на те приложения, которые больше других нагружают систему. У меня, как видите, есть возможность скрыть системные процессы, с которыми мы сделать ничего не можем, и показывать только установленные мною приложения. В числе таких гигантов я лично заметил, например, популярную сеть Тик Ток и Фейсбук.
Автозагрузка
Также у некоторых смартфонов есть встроенный редактор автозагрузки приложений. Ну или его можно также на один раз установить из магазина приложений. Для примера можно привести «Boot Apps» или «Auto Start Manager». Таких программ тоже очень много.
Устанавливаем приложение, даем ему разрешения и в нем уже отключаем вообще все. Это позволит нам при старте системы сохранить максимальное число оперативной памяти и загружать туда только то, что действительно необходимо. Было такое, что в автозагрузку себя прописывали даже разные игры, установленные «от нечего делать». Подобный расход полезных мощностей должен быть немедленно пресечен.
Системное ограничение числа фоновых процессов
Системное ограничение числа фоновых процессов я лично трогать не рекомендую, так как всякие социальные сети уже давно стали актуальной нормой общения, и постоянная выгрузка их из памяти только добавит только лишних проблем.
Главное придерживаться разумного их количества. Восемь-десять социальных сетей в активном режиме даже современный флагман могут неслабо так нагрузить, что уж говорить о аппаратах пятилетней давности.
Однако у тех же смартфонов Xiaomi я нашел интересную функцию, позволяющую выгружать некоторые приложения из памяти. Это полезно, так как на социальные сети можно поставить запрет, а, например, на тайм киллер — нет.
Однако ставить для этих целей какие-нибудь внешние менеджеры я лично не рекомендую. Так что внимательно изучите настройки производительности своего устройства. Может там есть что-то еще удобнее.
Альтернативная память для системы
Еще один интересный прием пригодится, если вы купили актуальный, но достаточно бюджетный “китайский” телефон для своих родителей или ребенка. У меня вот как раз такой случай. Проблема тут заключается в том, что обычно в них экономят на всем, включая даже системную память. То есть она тут банально очень медленная. Но решение есть. Достаточно установить в такой смартфон любую современную карту памяти и назначить ее системной.
Сделать это очень просто, достаточно установить такую карточку в смартфон и включить его. Телефон сам спросит использовать данную карточку в виде системной памяти или просто как внешний накопитель. Выбирайте первый пункт и сами увидите насколько положительно это скажется на скорости работы.
Без подобного финта мой старый XGODY буквально ходил пешком, теперь же им вполне можно пользоваться.
Если ничего не помогло
Однако бывают ситуации, когда даже эти методы оказываются неэффективными. В этом случае поможет полный сброс устройства до заводских настроек. Обычно эта функция находится в «Настройки» — «Система» — «Сброс настроек». Предварительно обязательно сохраните все важные вам данные в облако, на флешку или в любое другое место, поскольку все это будет принудительно удалено. Сам я обычно делаю бэкап системы и переношу папку с ним на компьютер, чтобы после процесса очистки снова развернуть на систему. Но это лучше придержать на совсем уж крайний случай.
Послесловие
Уверен, при помощи приведенных простых, но безусловно важных шагов вы легко сможете ускорить не только свой смартфон, но и помочь менее опытным пользователям легко справится с подобными проблемами. Если же у вас есть собственные идеи относительно данной тематики, обязательно оставляйте их в комментариях.
Источник