Детальное использование аккумулятора – iOS

Мой текущий проект – приложение постоянного присутствия (думаю, Tinder или Foursquare), а потребление батареи – через крышу. Мы считаем, что основной потребностью в мощности являются GPS и WiFi антенны. Мы хотели бы измерить потребление энергии нашим приложением в нескольких разных конфигурациях.

Но как это сделать? Нам нужен процесс, который:

  • Может использоваться с телефоном, отключенным от компьютера (поэтому мы знаем, что мы используем аккумулятор, а не мощность питания через USB),
  • Имеет достаточную детализацию, чтобы позволить нам сопоставлять энергетические всплески с событиями приложений (запуск приложения, обновление местоположения, отправка информации аналитики в Mixpanel и т. Д.),
  • Может быть проведен на ночь без няни,
  • Может быть экспортирован как CSV или что угодно для статистического анализа.

В общем, я знаю.

Таковы требования, и вот варианты, о которых я знаю:

1. Включение необработанной диагностики энергии. Регистрация на устройстве iOS и экспорт в Инструменты

Это очевидный ответ, но он имеет один гигантский недостаток.

Плюсы:

  • Использует аккумулятор вместо мощности USB.
  • Отличная зернистость (данные временных рядов 1 с, 20 уровней дискретного энергопотребления),
  • Связано с другими событиями устройства, такими как использование антенны GPS и т. Д.

Минусы:

  • Нельзя запускать на ночь, потому что «если батарея устройства разряжается или устройство iOS выключено, данные журнала теряются». Это ограничение CRAZY, и в значительной степени делает этот подход бесполезным для нашего случая ( https://developer.apple.com/library/ios/recipes/Instruments_help_articles/LoggingEnergyUsageinaniOSDevice/LoggingEnergyUsageinaniOSDevice.html ).
  • Не удается экспортировать в CSV. Потому что Инструменты.

2. Мониторинг подключенного телефона через инструменты

Плюсы:

  • Такая же отличная гранулярность и корреляция с другими событиями устройства.
  • Батарея не может разрядиться.

Минусы:

  • Не использует батарею, поэтому потребление энергии несравнимо с использованием в реальном мире.
  • Инструменты даже не надежно показывают потребление энергии. Иногда это просто пусто.
  • Не удается экспортировать в CSV.

3. Использование общедоступных API-интерфейсов Cocoa для записи потребления энергии в нашем приложении – [UIDevice.currentDevice batteryLevel]

Это самый распространенный ответ на SO. Я посмотрел на расчетное время работы аккумулятора на iOS , iphone: расчет времени автономной работы и около десятка других.

Плюсы:

  • Произвольно небольшое время между измерениями.
  • Могут сохраняться данные, даже если батарея умирает, записывая на диск как-то (CoreData, по умолчанию, сеть, что угодно).
  • Можно выбрать произвольный формат данных, например CSV.

Минусы:

  • Гораздо больше работы, чем другие подходы.
  • Открытый API дает вам уровень заряда аккумулятора до 5% точности. Это по существу интеграл во времени мгновенных данных энергопотребления, которые мы получаем из подходов 1 и 2. Не достаточно гранулированный, чтобы коррелировать с другими событиями устройства (но, возможно, достаточно, чтобы получить общую оценку времени автономной работы устройства).

4. Использование частных API-интерфейсов Cocoa для записи потребления энергии

Поскольку мы будем делать это только во время разработки, не имеет значения, отклонит ли Apple приложение для использования частного API. Предположительно, для этого есть частный API, так как Apple может записывать данные с помощью Untethered Energy Diagnostics.

Плюсы:

  • Произвольная детализация, произвольный формат файла, произвольная настойчивость.

Минусы:

  • Waaaaay больше работы, чтобы выяснить, как его использовать. Возможно, даже не возможно.

5. Комбинированный подход

Мы могли бы использовать необработанную диагностику для количественной оценки предельной стоимости энергии для каждого действия. «Хорошо, вращающаяся антенна GPS занимает 150 мВт • H. Расчетное положение занимает 50 мВт • H. Отправка события Mixpanel занимает 25 мВт • H, если только мы не сделали другой сетевой вызов в течение предыдущих 30 секунд, и в этом случае он занимает 15 мВт • H." (все числа придуманы на месте.) Затем мы можем использовать привязанный мониторинг для записи, когда происходит каждое из этих действий , подключаться к линейному уравнению и оценивать количество энергии, которое оно должно было принять.

Плюсы:

  • Гибкое. Произвольное все.

Минусы:

  • Математика.
  • Очень легко пропустить нелинейные вклады. Получение чего-то вроде E = k0 / (интервал опроса gps) + k1 * (количество вызовов аналитики) легко, но что, если затраты на разворот обеих антенн меньше, чем сумма их разворачивания отдельно?
  • Игнорирует любые стратегии кэширования, которые Apple может сделать внутренне в службах геопозиционирования.
  • Даже не отдаленно близко к использованию в реальном времени.

Во всяком случае, я достаточно взбесился. Кто-нибудь делал это раньше? Как?

Не уверен, что это применимо к этому конкретному прецеденту, но я разработал библиотеку под названием UIDeviceListener которая позволяет вам легко (в основном с одной строкой кода) извлекать данные из операционной системы в отношении потребления энергии и многих других батарей / связанных с загрузкой данных: https://github.com/eldoogy/PowerData

Вот образец словаря, чтобы дать вам представление о том, какую информацию вы можете получить. Я обращу внимание на ключ InstantAmperage. Это показывает потребляемую мощность в режиме реального времени в мА для всего устройства (в то время как устройство отключено от сети). Это может помочь выполнить то, что вы ищете здесь.

 { AdapterDetails = { Amperage = 1000; Description = "usb host"; FamilyCode = "-536854528"; PMUConfiguration = 1000; Watts = 5; }; AdapterInfo = 16384; Amperage = 1000; AppleRawCurrentCapacity = 1279; AppleRawMaxCapacity = 1275; AtCriticalLevel = 0; AtWarnLevel = 0; BatteryData = { BatterySerialNumber = REDACTED; ChemID = 355; CycleCount = 524; DesignCapacity = 1420; Flags = 640; FullAvailableCapacity = 1325; ManufactureDate = REDACTED; MaxCapacity = 1273; MfgData = REDACTED; QmaxCell0 = 1350; StateOfCharge = 100; Voltage = 4194; }; BatteryInstalled = 1; BatteryKey = "0003-default"; BootBBCapacity = 52; BootCapacityEstimate = 2; BootVoltage = 3518; CFBundleIdentifier = "com.apple.driver.AppleD1815PMU"; ChargerConfiguration = 990; CurrentCapacity = 1275; CycleCount = 524; DesignCapacity = 1420; ExternalChargeCapable = 1; ExternalConnected = 1; FullyCharged = 1; IOClass = AppleD1815PMUPowerSource; IOFunctionParent64000000 = <>; IOGeneralInterest = "IOCommand is not serializable"; IOInterruptControllers = ( IOInterruptController34000000, IOInterruptController34000000, IOInterruptController34000000, IOInterruptController34000000 ); IOInterruptSpecifiers = ( <03000000>, <26000000>, <04000000>, <24000000> ); IOMatchCategory = AppleD1815PMUPowerSource; IOPowerManagement = { CurrentPowerState = 2; DevicePowerState = 2; MaxPowerState = 2; }; IOProbeScore = 0; IOProviderClass = AppleD1815PMU; InstantAmperage = 0; IsCharging = 0; Location = 0; Manufacturer = A; MaxCapacity = 1275; Model = "0003-A"; Serial = REDACTED; Temperature = 2590; TimeRemaining = 0; UpdateTime = 1461830702; Voltage = 4182; "battery-data" = { "0003-default" = <...>; "0004-default" = <...>; "0005-default" = <...}; "built-in" = 1; } 

UIDeviceListener поддерживает обычные, не вредоносные устройства iOS и не вызывает никаких частных API.

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

Общие источники чрезмерного потребления энергии:

  • Опрос вместо использования прерываний. это предотвращает переход процессора в более низкие уровни мощности. Низкое энергопотребление может снизить потребление процессора на порядок

  • Использование интервалов прерываний, которые слишком малы. Общей ошибкой является то, что меньший интервал опроса, скажем, 10 мс, приводит к более быстрому ответу. Если способность вашего приложения / пользователя отвечать – 500 мс, то 10 мсек только для того, чтобы процессор не спал и не пережевал энергию.

  • Все, что передает, – это свиньи, получающие меньше, но все же плохой (WiFi, GPS, Bluetooth и т. Д., Как сказано выше). Минимизируйте их использование.

  • Периферийные устройства также имеют маломощные состояния. Использует их экономно, чтобы держать их в более низком энергетическом состоянии.

Комментарии к измерению потребляемой мощности:

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

  • Большинство мониторинга происходит от ОС, что может быть или не быть от «реальных» измерений HW против «догадок» SW.

  • Попытка действительно быть точным означает более частые измерения, которые, как вы догадались, заставляют процессор и устройства бодрствовать.

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

GPS требуется 10% -ная батарея в час, поэтому она будет длиться около 10 часов высокой точной записи местоположения один раз в секунду. интервал опроса местоположения не имеет ничего общего с потреблением батареи. либо чип GPS включен, либо нет. Нет режима низкой мощности gps! вы можете отключить gps, если знаете, что пользователю это не нужно.

для постоянной записи данных о местоположении вы можете сэкономить только батарею, если вы решите пойти с низкой аккуратностью (1000-мегагерцовая башня или локализация wlan) вместо высоких (3-6 м = GPS)

конечно, во время измерения вы будете убивать все приложения для 3D-вечеринок, особенно приложения для обмена сообщениями, самый известный из них подключается к интернету каждую секунду!

  • UIButton в режиме Modal View через UIToolBar через UITabBar Touch не обнаружен
  • Могу ли я наблюдать, когда UIViewController изменяет интерфейсОриентации?
  • Crashlytics: обход IOS 9 для проблемы загрузки двоичных изображений
  • Можете ли вы программно вызывать сири?
  • Какая польза от параметра «Основной интерфейс» в настройках сборки для приложения iOS?
  • Как обращаться с метками в пользовательском представлении выноски?
  • Текущая неделя Начальная и конечная дата
  • Повторное использование пользовательского интерфейса (xib-файлы)
  • iOS: отображается черная строка состояния при загрузке изображения
  • Как получить этот шаблон в iOS?
  • Понимание системной логики для первого ответчика
  • Interesting Posts

    Невозможно использовать пользовательский шрифт в приложении iPhone.

    Добавить страницу pdf в существующую цель pdf-c

    Что происходит, проверяя адрес константы, такой как SKStoreProductParameterAffiliateToken?

    XCode 7 Autolayout Constraints: как сделать 2 изображения в горизонтальном положении в центре

    Другие флаги компоновщика отсутствуют в настройках сборки Xcode

    Я не совсем понимаю sendSubviewToBack. Пожалуйста, смотрите код

    iOS: предупреждения C ++ в компиляторе после обновления до Xcode 8.3

    Развертывание и тестирование приложения на устройстве

    Международная клавиатура сбой приложения на устройстве

    Включить некоторые части UILabel, чтобы действовать как UIButton?

    Проблема с памятью с ARC

    Уведомление о сбое с помощью синтаксиса

    Скрыть навигационную панель, в зависимости от того, как появился контроллер просмотра

    Возврат UITableViewCell в обычный режим редактирования

    NSBlockOperation, NSOperationQueue и блоки

    Давайте будем гением компьютера.