iOS性能優化之耗電量

NO IMAGE

iOS性能優化之耗電量

前言

最近在測試App的時候,發現手機特別容易發燙,我們都知道 ,如果手機容易發燙,那麼耗電量肯定會相當大,手機電量使用的時間也會相對少;對此,我在工作之餘抽了點時間,對手機的耗電量進行了一些研究,希望可以給大家起到拋磚引玉的作用,對自己的App進行相應的優化,(在我們的能力範圍內 ,系統問題我們暫時沒還得靠蘋果大佬那邊進行優化)讓我們的手機電量的使用時間更長些。

一、耗電量相關知識的瞭解

為了更好的去優化手機的耗電量 ,我查看了蘋果官方文檔相關的資料,分別主要需要了解的有以下幾點:
Apple文檔:

  1. 入口: UIKit — App Structure (Core APP) — Device Environment (UIDevice) — Getting the Device Battery State 到這裡 ,我們就可以看到 耗電量有幾個個重要屬性batteryStateThe battery state for the device.

  2. iOS性能優化之耗電量

  3. @property(nonatomic, readonly) float batteryLevel; 電池電量範圍從0.0(完全放電)到1.0(100%充電)。在訪問此屬性之前,請確保已啟用電池監視。

如果未啟用電池監控,則電池狀態為且此屬性的值為-1.0。UIDeviceBatteryStateUnknown

  1. 耗電量的狀態

  2. UIDeviceBatteryState設備的電池電量狀態。

  3. UIDeviceBatteryState設備的電池電量狀態。

  4. UIDeviceBatteryState設備的電池電量狀態。

UIDeviceBatteryState設備的電池電量狀態。分別有如下幾種:UIDeviceBatteryStateUnknown無法確定設備的電池狀態。

UIDeviceBatteryStateUnplugged設備未插入電源; 電池正在放電。

UIDeviceBatteryStateCharging設備已接通電源,電池電量低於100%。

UIDeviceBatteryStateFull設備已接通電源,電池100%充電。

二、耗電量的基本概念

iOS性能優化之耗電量

圖一

通過這張圖,我們大概可以瞭解 ,我們的手機的耗電量,主要的狀態:

  1. Idle 狀態說明 app 處於休眠狀態,幾乎不使用電量。
  2. Active 狀態說明 app 處於前臺工作狀態,用電量比較高,我們可以看到圖中的第二個 Active 的耗電遠高於第一個,這主要因為 app 實際所做的工作類型不同而導致的。
  3. Overhead 指的是調起硬件來支持 app 功能所消耗的電量(原文是 bring hardware up)。note:如果你的 app 就算只做了一點點事,Overhead 所帶來的電量消耗都是一點不會減少的!
    圖中,橫線以下所包區域是固定開銷(Fixed Cost),橫線以上區域是動態開銷(Dynamic cost)。

三、影響電量的因素

  1. CPU 處理(Processing)
  2. 網絡(Networking)
  3. 圖像(Graphics)
  4. 定位(Location)

(1)首頁我們針對CPU和能耗的關係:CPU使用量越大,功率越大,電能消耗越多,電池消耗也就越快。功率大小由於設備、處理器、其他硬件資源等會有所不同,表1基於閒置狀態(idle state),給出了不同CPU使用量的一個大致的對比。

iOS性能優化之耗電量

我們在使用我們app執行任務有動態能耗(dynamic cost)和固定能耗(fixed cost)。

  1. 動態能耗也就是app實際工作消耗的能量。
  2. 固定能耗是在任務執行前後把系統和各種資源調用起來和關閉所消耗的能量。出現大量零散的工作時,在零散的任務之間因為資源可能永遠沒法真正變為閒置,所以有動態能耗的同時固定能耗也很高。這種情況導致大量電能在相對較小的實際工作中流失了。下圖是動態能耗和固定能耗圖
    如圖一

四、優化方案

1. 減少固定能耗交換動態能耗

你的app可以通過分批執行、降低執行頻率來避免產生零散的任務。例如,不採用同一個線程串行執行一系列任務,而是把任務同時放到多個線程,如圖所示。每次使用CPU,內存、緩存、總線等都得通電。通過分批執行,使用時間也更短。因為給定時間內做了更多的工作,需要更多能量,這種策略會導致更大的前期動態功耗。作為交換,固定能耗減小了,隨著時間推移,這會極大地節省電能。你的app提高了功率,但它更高效,用了更少的時間。這使得CPU回到閒置狀態,其他元件也更快地斷電

iOS性能優化之耗電量

圖2

2. 少使用定時器或者用高級的定時器

GCD裡的dispatch queues、dispatch semaphores等同步工具比定時器效率高很多,儘量不要用定時器做同步工具。所有需要指定一個最後期限的函數或方法都屬於定時器,比如:
a. 高級定時器包括dispatch timer sources、CFRunLoopTimerCreate和其他CFRunLoopTimer函數、NSTimer、performSelector:withObject:afterDelay:方法。
b. 底層定時器包括sleep, usleep, nanosleep, pthread_cond_timedwait, select, poll, kevent, dispatch_after, dispatch_semaphore_wait。
如果一定要用定時器,儘量高效地使用,可以參照下列指導方針:

  1. 設置一個合適的超時時間。
  2. 不再需要時及時關閉重複性定時器。
  3. 設置觸發公差。

3. 使用低電量模式

iOS9之後,iPhone增加了低電量模式,用戶如果希望延長iPhone電池的壽命,可以在設置 > 電池中開啟該功能。開啟該功能之後iOS會採取一些措施,比如:

  1. 降低CPU和GPU性能
  2. 暫停隨意的和後臺的活動,包括網絡
  3. 降低屏幕亮度
  4. 縮短自動鎖屏時間
  5. 關閉郵件刷新
  6. 關閉視角縮放
  7. 關閉動態壁紙

4.縮減網絡請求

  1. 減少、壓縮網絡數據。可以降低上傳或下載的多媒體內容質量和尺寸等。
  2. 使用緩存,不要重複下載相同的數據。
  3. 使用斷點續傳,否則網絡不穩定時可能多次傳輸相同的內容。
  4. 網絡不可用時不要嘗試執行網絡請求,儘量只在Wi-Fi情況下聯網。
  5. 讓用戶可以取消長時間運行或者速度很慢的網絡操作,設置合適的超時時間。

5. 延遲聯網和 圖像、動畫、視頻優化

  1. 延遲網絡:分批傳輸。比如,下載視頻流時,不要傳輸很小的數據包,直接下載整個文件或者一大塊一大塊地下載。如果提供廣告,一次性多下載一些,然後再慢慢展示。如果要從服務器下載電子郵件,一次下載多條,不要一條一條地下載。網絡操作能推遲就推遲。如果通過HTTP上傳、下載數據,建議使用NSURLSession中的後臺會話,這樣系統可以針對整個設備所有的網絡操作優化功耗。將可以推遲的操作儘量推遲到設備充電狀態並且連接Wi-Fi時進行,比如同步和備份工作。
  2. 圖像 減少不透明視圖的使用,比如視圖上顯示一個半透明模糊效果。如果要用不透明效果,避免用在內容頻繁變化的地方。另外,由於內容變化後背景視圖和半透明視圖必須同時改變,這也會放大功耗。
  3. 避免繪製不可見的內容,比如app的內容被其他視圖遮擋、被剪切(clipped)或者出畫了。
  4. 動畫儘可能用較低的幀率。比如,高幀率在玩遊戲時有意義,但是菜單畫面可能較低的幀率就夠了。只有對用戶體驗有影響時才使用高幀率。

6. 優化定位

如果你的app只是需要快速確定一下用戶的位置,最好用CLLocationManager的requestLocation (iOS9引入)方法。定位完成之後會自動讓硬件斷電。
除了導航,大多數app不需要一直實時更新位置。需要位置服務時開啟一下定位,儘量多隔一些時間再進行下次位置更新,更新完了之後馬上關掉定位。除非用戶在移動的交通工具裡,否則不頻繁地更新位置一般沒多大問題。降低定位精度。iOS設備默認採用最高精度定位,如果你的app不是確實需要米級的位置信息,不要用最高精度(kCLLocationAccuracyBest)或10米左右的精度(kCLLocationAccuracyNearestTenMeters)。一般來說Core Location提供的精度比你設置的要好,比如你設置為3公里左右的精度,可能會收到100米左右的精度信息。
如果定位精度一直達不到設置的精度時,停止更新位置,稍後再試。
需要後臺更新位置時,儘量把pausesLocationUpdatesAutomatically設為YES,如果用戶不太可能移動的時候系統會自動暫停位置更新。

7. 代碼層面優化

  1. 合理使用NSDateFormatter 和 NSCalendar這種高開銷對象
    性能測試表明,NSDateFormatter的性能瓶頸是由於NSDate格式到NSString格式的轉化,所以把NSDateFormatter創建單例意義不大.推薦的做法是,把最常用到的日期格式做緩存.
static NSDateFormatter *cachedDateFormatter = nil;
+ (NSDateFormatter *)cachedDateFormatter {
if (!dateFormatter) {
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat: @“YYYY-MM-dd HH:mm:ss”];
}
return dateFormatter;
}
  1. 不要頻繁的刷新頁面,能刷新1行cell最好只刷新一行,儘量不要使用reloadData.
  2. 選擇正確的集合
    NSArray,使用index來查找很快(插入和刪除很慢)
    字典,使用鍵來查找很快
    NSSets,是無序的,用鍵查找很快,插入/刪除很快
  3. 少用運算獲得圓角,不論view.maskToBounds還是layer.clipToBounds都會有很大的資源開銷,必須要用圓角的話,不如把圖片本身就做成圓角
  4. 懶加載,不要一次性創建所有的subview,而是需要時才創建.
  5. 重用
    可以模仿UITableView和UICollectionView,不要一次性創建所有的subview,而是需要時才創建.完成了使命,把他放入到一個可重用集合中
  6. 圖片處理
    圖片與imageView相同大小,避免多餘運算
    可以使用整副的圖片,增加應用體積,但是節省CPU
    可調大小的圖片,可以省去一些不必要的空間
    CALayer,CoreGraphics,甚至OpenGL來繪製,消耗CPU
  7. cache,cache,cache(緩存所有需要的)
    服務器相應結果的緩存(圖片)
    複雜計算結果的緩存(UITableView的行高)
  8. 儘量少用透明或半透明,會產生額外的運算.
  9. 使用ARC減少內存失誤,dealloc需要重寫並對屬性置為nil
  10. 避免龐大的xib,storyBoard,儘量使用純代碼開發

8.CPU層面優化

1.Timer的時間間隔不宜太短,滿足需求即可
2.線程適量,不宜過多,不要阻塞主線程
3.優化算法,減少循環次數
4.定位和藍牙按需取用,定位之後要關閉或降低定位頻率

數據採集步驟

由於直接數據採集會出現較大誤差,建議使用以下方法進行數據採集:
1.在設備上進入設置 > 2. 開發者 > 3. Logging > 4. Enery打開 > 5. Networking打開> 6.點擊 Start Recording > 7. 然後點開我們想要測試的App,進行測試,定好時間,> 8.時間到了後點擊 停止 Stop Recording > 9.在Instruments中選擇好設備,進入Energy Log > 10.選擇File > Import Logged Data from Device

參考文章:
內存洩漏對耗電量的影響
教你開發省電
耗電量基礎概念

相關文章

讀《CleanCode代碼整潔之道》之感悟

跨表查詢經常有,何為跨表更新?

我的2019歸零,2020走你

Flutter入門學習:Flutter簡介以及在macOS上搭建Flutter開發環境