Pull to refresh
VK
Building the Internet

Профилирование Android-приложений на потребление аккумулятора

Reading time 6 min
Views 62K


Думаю, что у каждого пользователя Android рано или поздно возникает необходимость понять, какое приложение за ночь съело всю батарею притом, что телефон лежал с погашенным экраном. Участь найденного виновника не завидна: чаще всего его просто удаляют. Итак, что же сделать, чтобы наши приложения использовали аккумулятор минимально? В статье я постараюсь дать ответ на этот вопрос и рассказать о подходах к уменьшению потребления аккумулятора, которые мне доводилось использовать.



Количественная оценка


Прежде всего, давайте договоримся, как будем измерять потребление батареи, чтобы наблюдать за прогрессом после тех или иных исправлений в коде. Все, что нам доступно, — это процент заряда батареи. На него и будем ориентироваться. Эта величина меняется в зависимости от очень многих факторов.

Чтобы уменьшить ошибку измерения, желательно:
  • использовать одно и то же устройство;
  • использовать одну и ту же часть шкалы (дело в том, что изменение на один процент заряда на разных частях шкалы означает изменение на разный заряд, например, от 100% до 99% обычно разряжается быстрее, чем от 90% до 89%);
  • перед началом серии тестов на батарею на устройстве желательно сделать factory reset;
  • перед каждым тестом перезагружать устройство;
  • во время одного теста разряжать устройство более чем на 10%, чтобы погрешность измерения была не очень велика;
  • не ставить и не запускать никаких новых приложений во время серии тестов, они в фоне могут потреблять батарею;
  • не менять настройки устройства: яркость экрана, настройки сети и т.д.;
  • не перемещать устройство на существенные расстояния (более нескольких метров) во время теста или при каждом тесте перемещать его по одной и той же траектории.

На что же уходит батарея?


Главные потребители батареи это:
  • работа CPU;
  • подсветка экрана;
  • работа GPU;
  • работа с сетью;
  • частые получения GPS-координат.

Думаю, этот список знаком многим Android-разработчикам. Самое интересное, каков вклад каждого из этих пунктов. Конечно, он может быть разный. И вот мои наблюдения.
  • CPU часто главный потребитель;
  • на подсветку экрана часто уходит не меньше, чем CPU;
    Очень важно не менять яркость подсветки во время сравнительных тестов. Иначе это может исказить результат. Например, когда я замерял, как влияет изменение яркости на потребление батареи на Nexus 5, который прослужил более года, то получил такой результат: изменение яркости экрана с 20% до 80% увеличило потребление батареи на 15% в час.
  • потребление на работу сети может существенно возрасти, если телефон движется и если плохой сотовый сигнал;
    Это связано с затратами на поиск сотовых точек. Как и в случае с яркостью экрана, надо учитывать, что это может повлиять на результаты тестов.
  • эффект от потребления на получение GPS-координат часто усиливается тем, что при обновлении координаты вызывается callback, в котором исполняется определенный объем кода.

На что же мы можем повлиять, чтоб уменьшить потребление батареи приложением? На самом деле, не на многое.
  • Прежде всего это уменьшение нагрузки на CPU. Это главный способ уменьшить расход батареи. Имеет смысл спрофилировать приложение на использование CPU. Если возможно, перенести часть нагрузки на GPU. Это может дать существенный вклад.
  • Затем сеть. Данные имеет смысл буферизировать, чтоб реже обращаться по сети. Здесь подробно описано, как уменьшить потребление батареи при передачи данных по сети.
  • Далее GPS. Если не требуется точная, часто обновляемая координата не запрашивайте её. Стоит рассмотреть возможность определения координаты по WiFi. Здесь хорошо написано про это.


Профилирование потребления батареи


Нам понадобится:
  • Android-устройство с OS 5.x и достаточно новым аккумулятором. Если это возможно, ему лучше сделать factory reset.
  • Профилировщик: github.com/google/battery-historian. Его нужно установить на десктоп и опробовать до тестов.

Каждый эксперимент состоит из следующих шагов:
  1. Полностью заряжаем батарею. Это важно, чтобы потом была возможность сравнивать результаты экспериментов между собой на одной и той же части шкалы батареи.
  2. Устанавливаем на устройство тестируемое приложение.
  3. Перезагружаем устройство. Это нужно, т.к. иначе другие приложения, запущенные в фоне, могут повлиять на результат.
  4. Сбрасываем статистику батареи: adb shell dumpsys batterystats --reset
  5. Можно также включить статистику по wakelock. По умолчанию она выключена: adb shell dumpsys batterystats --enable full-wake-history
  6. Не забываем отключить девайс от компьютера, чтобы не заряжался.
  7. Затем, запускаем тестируемое приложение.
  8. И откладываем устройство на несколько часов, так чтобы оно разрядилось как минимум на 10-15%. Во время теста желательно не трогать устройство и не включать ему экран, поскольку это может повлиять на результат.
  9. Изучаем данные за время теста.

На последнем шаге остановлюсь подробно. Изучать данные теста можно двумя способами. Можно при помощи профилировщика, разработанного Google. А можно при помощи UI в настройках Android.

1. Профилировщик battery-historian
Прежде всего, профилировщик показывает разные UI для Android 5.x и для более ранних версий ОС. Притом, количество, полнота данных и удобство отображения заметно отличаются в пользу Android 5. С другой стороны, результаты профилирования приложения на батарею могут заметно отличаться, если запускать его на разных версиях Android. Я рекомендую начинать профилирование с Android 5, а затем обязательно повторить процесс на более ранних версиях ОС.

2. UI в настройках Android
Тут все просто. На телефоне заходим в Настройки -> Батарея. Проценты означают, сколько процентов батареи потрачено на каждое приложение. За 100% принимается все, что было потрачено за время теста.



Например, экран выше показывает, что статистика собрана примерно с 22 вечера до 7:30 утра. За это время устройство разрядилось на 72% (100% — 28%). 14% от того, на что разрядилось (т.е. от 72%) ушло на экран. 12% на MAPS.ME. Если клинуть на пункт в этом списке, то можно получить детальную информацию о расходе для выбранного приложения. На этом экране также видно, что потребление резко возросло с 6 до 7 часов. Нередко бывает, что приложение активно использует Службы Google, и расход заряда списывается на них. Это также видно на скриншоте выше. Этот диалог позволяет быстро понять, что происходит с приложением на фоне остальных приложений и сервисов, запущенных системой. А в случае Android 4.x и более ранних он дает данные, которые не получить при помощи профилировщика.

Работа с профилировщиком battery-historian


Для начала профилировщик необходимо установить. Подробно процесс установки описан здесь. Он включает в себя:
  • установку go: golang.org/doc/install
    Если вы установите go, как предложено по умолчанию, в директорию $HOME/go, то достаточно задать следующие переменные окружения, после установки:
    export GOPATH=$HOME/go
    export GOBIN=$GOPATH/bin
  • установку protobuf;
  • установку профилировщика battery-historian.

Далее подключаем устройство и забираем информацию о расходе батареи с момента последнего сброса данных о заряде (он происходит, если батарея зарядилась полностью или если была вызвана команда: adb shell dumpsys batterystats --reset):

adb bugreport > bugreport.txt

Запускаем профилировщик:

cd $GOPATH/src/github.com/google/battery-historian
go run cmd/battery-historian/battery-historian.go

Заходим в браузере по адресу:
http://localhost:9999

В открывшемся окне выбираем ранее сохраненный файл bugreport.txt.

Результаты, которые вы увидите в браузере, будут зависеть от версии Android, с которой был загружен bugreport.txt. Для Android 5.x отображается страница с рядом вкладок и самой разнообразной информацией, включая статистику по каждому приложению системы. Общая статистика расхода батареи на устройстве:





Статистика по приложениям:



Для Android 4.x получим вот такой диалог. Он существенно менее информативен, но по нему можно понять, что происходит с потреблением в целом.



Режимы профилирования приложения


Имеет смысл провести проверку как минимум в двух режимах:
  • приложение на переднем плане;
  • приложение в фоне.

Желательно, чтобы приложение в фоне вообще не потребляло ресурсов, если на то нет очень веских причин. Кроме того, часто стоит отдельно проверить, как приложение потребляет батарею во время движения. Особенно, если оно использует GPS или как-то иначе связано с локацией.

Деградация аккумулятора


Важно учитывать, что со временем заряд аккумулятора слабеет. У меня был случай, когда за полгода приложение стало разряжать аккумулятор в полтора раза быстрее. Причина — старение батареи. Это стоит учитывать при тестах. Если приложение съедало всю батарею устройства за 4 часа работы полгода назад, то, скорее всего, сейчас оно будет съедать батарею за меньшее время. И причина не в том, что в приложении что-то стало не так.

Сравнение с конкурентами


Хочу обратить внимание, что приведенные выше методики не требуют доступа к исходным кодам приложения. Это значит, что можно сравнить, как ваше приложение потребляет аккумулятор по сравнению с конкурентами.

Заключение


В этой статье я описал подходы по уменьшению потребления батареи, которые мы применяем при работе над MAPS.ME в Mail.Ru Group. Было бы интересно услышать, если кто-то использует какие-то другие средства и технологии для решения этой же задачи. Пишите в комментариях.
Tags:
Hubs:
+18
Comments 15
Comments Comments 15

Articles

Information

Website
vk.com
Registered
Founded
Employees
5,001–10,000 employees
Location
Россия
Representative
Миша Берггрен