iOS 電量消耗改善:一招套路及相關姿式

工做流

解決電量問題的工做流:

先使用 Xcode Energy Gauge 分析出哪一塊耗電(網絡和 motion , 仍是定位 ... ), 用 Time Profiler 定位問題與解決 ( Instruments 模版 ), 獲得用戶好的反饋。html

三個原則:
  • Do it never/do it less (能不作,就不作。少作的,好)

好比: 網絡請求,先壓縮數據git

  • Do it at a better time (合適的時機處理 )

網絡請求,使用緩存機制,設置內容驗證( 須要的數據是否更新了 ),或者緩存的失效時間github

  • Do it efficiently ( 有效處理 )

合併網絡請求。一次請求大量數據,比屢次請求少許數據省電swift

(類比 CPU,線程開多了很差。開線程,就會有消耗)api


套路很簡單,將手機放在桌子上,Xcode 裏面啓動 app, 並檢測,啥也不幹。若是電量消耗較高,很不合適了

WWDC 推薦使用 Xcode Debug 欄的 Energy Debug Gauge。xcode

( 調性能,都是用真機。機器老一點,效果更好 )緩存

Energy Debug Gauge 形象、直觀bash

Energy Debug Gauge

可看出,當前手機的耗電狀況,耗電低、高、很高。蘋果的三個階段,有些不太細緻。(左上的 Utilization, Current Impact)網絡

app 的平均能耗,一目瞭然 ( 右上的 Average ) 。app

每個時刻,耗電的是什麼。 CPU 、網絡、文件 I/O 、定位,哪些消耗了。( 中間的 Energy Impact )


Xcode Energy Gauge 能夠快速定位問題,想要進一步的細緻分析,下面有各類選項,跳轉到對應的 Instrumens 模版。

好比:

分析 CPU 使用的 time profile, (可以知道代碼的執行狀況了,根據函數的調用消耗。找出權重大的,幹掉沒必要要的。)

分析網絡活動的 network profile, 分析定位活動的 location profile

跳


本文示例代碼: 解決的兩個問題,給 CoreMotion 更新設置過濾,幹掉頻繁的日誌上傳

before

這裏電量消耗很高,很穩定

主要是 CPU 和網絡請求在耗電。


使用 Instruments 的 Time Profiler 分析,

CPU 分析

能夠先放大上面的 time line,再選擇一個時間段,在調用樹 call tree 中,進一步分析。

Time Profiler 的選項默認是按線程劃分的,再選一個隱藏系統調用函數。

(系統執行的函數,能夠參考一下,到底發生了什麼。系統的改不了。能夠改本身的源代碼 )

option

在調用樹的表格中,按權重展開 ( weight ),要幹掉的就是權重大的,耗時間的。

接着展開主線程 ( main thread 。看上圖,其餘線程的耗時,相比主線程的,可忽略 ), 按住 Option 鍵,點擊 main thread 左邊的小三角,能夠一會兒展開不少。

可清晰看出,耗時嚴重的是 450 毫秒左右的那一行 thunk for ... CMDeviceMotion? ...

裏面調用了一個耗時的方法,CatPhotoTableViewCell.panImage , 上圖, 454 毫秒中,佔 419 毫秒。

hop

點擊進入詳情,就看到代碼了。

在 CatFeedViewController 的 viewDidLoad 方法中,有一個傾斜的設置

motionManager.startDeviceMotionUpdates(to: .main, withHandler:{ deviceMotion, error in
            guard let deviceMotion = deviceMotion else { return }
            let xRotationRate = CGFloat(deviceMotion.rotationRate.x)
            let yRotationRate = CGFloat(deviceMotion.rotationRate.y)
            let zRotationRate = CGFloat(deviceMotion.rotationRate.z)
            //  y > z, 這個動做是翹起來
            //  y > x + z, 這個動做是斜着翹起來
              if abs(yRotationRate) > (abs(xRotationRate) + abs(zRotationRate)) {
                for cell in self.tableView.visibleCells as! [CatPhotoTableViewCell] {
                    cell.panImage(with: yRotationRate)
                }
              }
  })
複製代碼

如今的代碼顯示欄 ( 原來的 Call Tree 表格 ), 右上角有一個 Xcode 的小圖標,點擊返回 Xcode 調試代碼。

手機沒動,總是調用 cell.panImage(with: yRotationRate), 根本就沒效果。

設置一下,調用 cell.panImage 的時候,要超過最小的手機幅度。幅度小,根本就沒效果。 添加一個屬性記錄 lastY 來設置,過濾掉手機小的抖動。

private var lastY = 0.0
override func viewDidLoad() {
        super.viewDidLoad()
        ......
        motionManager.startDeviceMotionUpdates(to: .main, withHandler:{ deviceMotion, error in
            guard let deviceMotion = deviceMotion else { return }
          
            // 添加了這兩行
           guard abs(self.lastY - deviceMotion.rotationRate.y) > 0.1 else { return }
            self.lastY = deviceMotion.rotationRate.y

            let xRotationRate = CGFloat(deviceMotion.rotationRate.x)
            let yRotationRate = CGFloat(deviceMotion.rotationRate.y)
            let zRotationRate = CGFloat(deviceMotion.rotationRate.z)
              if abs(yRotationRate) > (abs(xRotationRate) + abs(zRotationRate)) {
                for cell in self.tableView.visibleCells as! [CatPhotoTableViewCell] {
                    cell.panImage(with: yRotationRate)
                }
              }
        })
    }
複製代碼

還有一個使用 Timer 定時發送日誌的問題,CPU 根本沒有空閒的時間,開銷很大。

具體見文末的 Demo Code.

最後這樣

after

會慢慢降下去,至於電量低消耗。 須要大約兩分鐘時間,一屏幕放不下。


Instruments 的 Energy Log 有問題,連着 Xcode 實時調試的部分 gg 了

Instruments 的 Energy Log 模版用途不大

由於不能手機在線調試。Energy 是空的, 或者提示 No Data,

這是蘋果的一個長期的 bug .(參見 Apple Forum )

Energy Log 模版的模塊挺豐富的,能夠看屏幕亮度、定位、藍牙、GPU 和網絡等等的功耗狀況,其中網絡又包括 WiFi 和蜂窩網絡。


想着一邊給手機充電,一邊調試電量損失,不靠譜。

試了下,無線用 Instruments 的 Energy Log 模版調試,結果同樣。

無線鏈接 Xcode 調試耗電,也沒有數據。


無線用 Instruments 調試,首先要設置 Xcode 無線 Debug ,

無線 debug 功能,隱藏在 Xcode 的 Window > Devices and Simulators 中。

Devices_and_Simulators

其實是,使用共享的無線網絡,取代了數據線的鏈接,與 Xcode 創建鏈接。

會有一個網絡的 Icon . 上面還有提示語 ( connected , 連上了 )

以下圖:

connect

更多參見博客 How to use Wireless Debugging on Xcode 9

而後就能夠設置 Instruments 無線設備調試了,

更多參見蘋果文檔 Energy Efficiency Guide for iOS Apps


instruments 的 Energy 模版,將電量消耗的程度劃分爲 20 個級別。 0 表明不耗電,天然 app 沒作什麼 20 表明耗電嚴重

WWDC 中說,要看到,就導入離線的 log。(幾個月之前,還能用)

在手機的設置中,開發者選項中的 Logging, 選中 Energy, 點擊開始錄製:

開發者

以後,使用你的 app 一段時間,(能夠重點測耗電功能) 開發者選項中的 Logging, 點擊完成錄製, 導入電量消耗 log 數據,到 Instruments 的 Energy Log 模版.

導入

推測老版本的不行( 11.4 ), 沒數據。操做的時候,手機的設置 app ,還總是閃退。

手機升級到最新版(12.1 , 20181127),試了屢次,也不行, 猜想目前是完全掛了

(本文中,重啓過手機,升級過手機。沒試太重啓電腦)


溼一點,好消化

耗電是很差的。

寫入硬盤與網絡請求,都是高耗電操做。

網絡請求特別耗電,每個網絡請求,手機設備須要使用他的蜂窩網絡天線,發送無線電波。

網絡的質量與類型,對於耗電的影響也很大。 使用 Wi-Fi 比 3G , 4G 要省電得多。 使用 4G 比 3G 要省電,由於 4G 的信號更強。

計時器,能不用就不用。( NSTimer )

通常狀況下,app 都用 Timer 作了不少無用功。

好比, 一個列表屏幕, 上方 banner 計時器,往下滑到看不見 banner ,就能夠暫停計時器。上滑,看得見 banner 了,又能夠恢復 resume。

一樣的,進入子界面,能夠選擇暫停 Timer,或者釋放,...

例子: 定時作重複的大量工做很差,可能每當系統休眠(系統要下降能級了),系統又被喚醒了,開始功耗。

定位

與網絡請求相似,手機設備定位經過 GPS 天線發送信號,也挺耗電的。

若是 app 常常去獲取手機設備的精肯定位,定位精度越高,能耗越嚴重。 建議使用策略,手機的負擔會小不少。

( 🌰,Deferred location updates, 位置更新延遲(直到移動了 x 米或者時間超過了 xx 秒 )、

significant location change, 定位變化比較大的時候,喚醒、

region monitoring, 監測用戶進入或離開特定地理區域)

Motion 物理引擎,動態效果更新狀態,挺耗電的。

使用羅盤、陀螺儀、加速計,都消耗不小。


相關代碼: github.com/BoxDengJZ/I…

更多資料:

WWDC 2015 Debugging Energy Issues

視頻教程,practical-instruments


本文 Demo 使用的是 500 px 的 API .


後來發現, 有人都寫過了

好尷尬

想了一下,能夠寫他沒交代的。蘋果更新太快,人是物非

相關文章
相關標籤/搜索