iOSApp性能優化

性能優化-詳解web

性能測試:實時監測應用內存、CPU消耗緩存

                                                                                      部分性能指標及定義性能優化

性能指標                                指標描述網絡

應用首次啓動時間              測量系統從開始處理 activity到完成運行進入主界面的時間,即冷啓動響應時間多線程

界面幀率                              FPS指應用每秒渲染幀數,是用戶對應用界面所量現的畫面流暢度的體驗,FPS太低,用戶可感知的流暢度差。 併發

應用前臺運行內存佔用      應用在前臺且運行穩定時的內存佔用狀況app

應用後臺運行CPU佔用       應用在後臺且亮屏時的cPU佔用狀況。函數

CPU&GPU理解工具

 

CPU:中央處理器(Central Processing Unit)佈局

GPU:圖形處理器(Grphics Processing Unit)

 

屏幕成像原理

屏幕的顯示成像是結合CPU數據處理和GPU渲染而來的,即每次屏幕刷新時都會受到CPU和GPU的影響。CPU計算顯示內容(視圖的建立、佈局計算、圖片解碼、文本繪製等),完成後將計算好的內容提交到GPU,由GPU進行變換、合成、渲染,隨後GPU會把渲染結構提交的幀緩衝區去,等待下一此垂直同步信號到來時顯示到屏幕上。iOS系統圖形服務提供CADisplayLink等機制通知App,App在主線程開始上述操做。若是在一個刷新時間內,CPU或GPU沒有完成內容提交,則那一幀就會被丟棄,等待下一次機會再顯示,而此時顯示屏會保持以前的內容不變,從而產生掉幀狀況,從而致使界面卡頓。

 

屏幕成像原理

 

離屏渲染

在OpenGL中,GPU有兩種渲染方式

On-Screen Rendering : 當前屏幕渲染,在當前用於顯示的屏幕緩衝區進行渲染操做.

Off-Screen Rendering : 離屏渲染 ,在當前屏幕緩衝區之外新開闢一個緩衝區進行渲染操做.

 

離屏渲染消耗性能的緣由

1.須要建立新的緩衝區

2.離屏渲染的整個過程,須要屢次切換上下文環境,先是從當前屏幕(On-Screen)切換到離屏(Off-Screen);

當離屏渲染結束之後,將離屏緩衝區的渲染結果顯示到屏幕上,又須要將上下文環境從離屏切換到當前屏幕。

 

哪些操做會觸發離屏渲染

1.光柵化, layer.shouldRasterize = YES.

(rasterizedLayer柵格化的空間是有限的,iOS大概有屏幕大小兩倍的空間來存儲rasterizedLayer或是屏幕外緩衝區)若是設置了shouldRasterize=YES,也要設置rasterizationScale 爲 contentsScale.即

self.layer.shoudlRasterize = YES;
self.layer.rasteriztionScale = [UIScreen mainScreen].scale;

2.遮罩, layer.mask

3.圓角, 同時設置layer.masksToBounds = YES、layer.cornerRadious 大於0(經過CoreGraphics繪製裁剪圓角,或者美工提供圓角圖片)

4.陰影, layer.shadowXX (若是設置了layer.shadowPath就不會產生離屏渲染)

5.系統的切圓角也會觸發離屏渲染

  view.layer.cornerRadious = 5;
  view.layer.maskToBounds = true;

卡頓優化-CPU

1.儘可能用輕量級的對象,好比,用不到事件處理的地方,能夠考慮用CALayer代替UIView.

2.不要頻繁調用UIView的相關屬性,好比frame、bounds、transform等屬性,儘可能減小沒必要要的修改.

3.儘可能提早計算好佈局,在有須要時一次性調整對應的屬性,不要屢次修改屬性。

4.AutoLayout要比直接修改frame消耗更多的CPU資源。

5.圖片的size最好和UIImageView的size保持一致

6.控制一下線程的最大併發數量

7.儘可能把耗時的操做放在子線程

 

卡頓優化-GPU

1.儘可能避免短期內大量圖片的顯示,儘量將多張圖片合成一張進行顯示

2.儘可能減小視圖數量和層次

3.減小透明的視圖(alpha<1),不透明的就設置opaque爲YES.

4.儘可能避免出現離屏渲染

 

其餘

A.頻繁操做部分界面

B.自定義繪圖渲染(代碼)

C.App啓動(冷啓動、熱啓動)

D.選擇API 多線程/UIImageAPI

E.文件讀寫

F.APP太大了(如何給APP瘦身)?

G.內存使用不正確

耗電優化

耗電的主要來源:

耗電來源

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

定位優化:

  • 若是隻是快速確認位置,最好用CLLocationManager的requestLocation方法。定位完成後,會自動讓定位硬件斷電。
  • 若是不是導航應用,儘可能不要實時更新位置,定位完畢就關掉定位服務
  • 儘可能下降定位精度,好比儘可能不要使用精度最高的kCLLocationAccuracyBest
  • 須要後臺定位時, 儘可能設置pausesLocationUpdatesAutomatically爲YES, 若是用戶不太可能移動的時候系統就會自動暫停位置更新。
  • 儘可能不要使用startMonitoringSignificantLocationChanges, 優先考慮startMonitoringForRegin

App啓動優化

App啓動方式:

1.冷啓動:(Cold Launch): 從零開始啓動App

2.熱啓動(Warm Launch) App 已經在內存中,在後臺存活着,再次點擊圖標啓動APP

App啓動時間的優化主要針對冷啓動進行優化

經過添加環境變量能夠打印出來App的啓動時間分析(Edit scheme - >Run ->Arguments)

1.DYLD_PRINT_STRATISTICS設置爲1

2.若是須要更詳細的信息,那就將DYLD_PRINT_STRATISTICS_DETAILS設置爲1

App冷啓動大體分三個階段

dyld , Apple的動態連接器,能夠用來裝在Mach-O文件(可執行文件、動態庫)

啓動App時,dyld作的事

1.裝載App的可執行文件,同時會遞歸加載全部依賴的動態庫

2.當dyld把可執行文件、動態庫都裝載完畢後,會通知Runtime進行下一步的處理

runtime

1.調用map_images進行可執行文件的內容的解析和處理

2.在load_images中調用call_load_methods,調用全部的Class和Category的+load方法

3.進行各類objc結構的初始化(註冊Objc類、初始化類對象等等)

4.調用C++靜態初始化器和_attribute_((constructor))修飾的函數

到此爲止,可執行文件和動態庫中全部的符號(Class,Protocol,Selector,IMP…)都已經按照格式成功加載到內存中,被runtime管理。

main

1.App的啓動由dyld主導,將可執行文件加載到內存,順便加載全部的依賴的動態庫、

2.並由runtiem負責加載成objc定義的結構。

3.全部初始化工做結束後,dyld就會調用main函數

4.接下來就是UIApplicationMain函數,AppDelegate的application:didFinishLaunchingWithOptions:方法

App啓動優化

優化方案

1、dyld

       減小動態庫、合併一些動態庫(按期清理沒必要要的動態庫)

        減小Objc類、分類的數量、減小Selector的數量(按期清理沒必要要的類,分類)

        減小C++虛函數數量

        Swift儘可能使用Struct

2、runtime

        用+initialize方法和dispatch_once取代全部的__attribute__((constructor))、C++靜態構造器、ObjC的+load方法

3、main

       在不影響用戶體驗的前提下,儘量將一些操做延遲,不要所有都放在finishLaunching方法中,按需加載

 

⑥圓角終極優化方案

 

     /*
     實際中重繪圓角的優化方案須要考慮的是,將圖像從新繪製爲爲圓角圖像至關於多了一份拷貝,要不要緩存?A.第一次重繪後將這些圓角圖像緩存在磁盤裏,第二次加載直接使用緩存的圓角圖像;B.直接保存在內存裏,在內存比較吃緊時顯然不是個好選擇;C.不緩存,和系統圓角同樣,每次都重繪,浪費電量。
     */
     // 終極優化方案:
   /*
     //Ultimate Solution: Rasterization

     Typical use cases:
     Avoid redrawing expensive effects for static content
     Avoid redrawing of complex view hierarchies
     */
    func enableRasterizationOn(_ view: UIView) {
        view.layer.shouldRasterize = true
        view.layer.rasterizationScale = view.layer.contentsScale
    }

     總結

     1.RoundedCorner 在僅指定cornerRadius時不會觸發離屏渲染,僅適用於特殊狀況:contents爲 nil 或者contents不會遮擋背景色圓角;

   2.Shawdow 能夠經過指定路徑來取消離屏渲染;

   3. Mask 沒法取消離屏渲染;

     以上效果在同等數量的規模下,對性能的影響等級:Shadow > RoundedCorner > Mask > GroupOpacity(迷之效果)

 

     任什麼時候候優先考慮避免觸發離屏渲染,沒法避免時優化方案有兩種:

     1.    Rasterization:適用於靜態內容的視圖,也就是內部結構和內容不發生變化的視圖,對上面的全部效果而言,在實現成本以及性能上最均衡的。即便是動態變化的視圖,開啓 Rasterization 後可以有效下降 GPU 的負荷,不過在動態視圖裏是否啓用仍是看 Instruments 的數據。

     2.    規避離屏渲染,用其餘手法來模擬效果,混合圖層是個性能最好、耗能最少的通用優化方案,尤爲對於 rounded corer 和 mask。

⑦穩定App緩存

scrollViewDidScrollView,清除緩存

// 清除緩存
[[SDImageCache sharedImageCache] clearMemory];
// 設置緩存時長爲1個月
// [SDImageCache sharedImageCache].maxCacheAge = 30 * 24 * 60 * 60; 
// 清除沙盒中全部使用SD緩存的過時圖片(緩存時長 > 一個星期)
//  [[SDImageCache sharedImageCache] cleanDisk];
// 清除沙盒中全部使用SD緩存的圖片
//  [[SDImageCache sharedImageCache] clearDisk];

UITableView-hightForRow調用時機+Cell行高計算(緩存)

內存優化分析 如何檢測內存方面的問題

 公共配置:

A:打開全局斷點, 殭屍對象檢測,Zombie Objects 進行野指針的檢測

  [Person release]: message sent to deallocated instance 0x60400001e690

B:打開全局斷點

C.(dealloc方法)析構方法打印看調沒調用

常見問題彙總: 

循環引用 / 錯誤的內存訪問 / 內存消耗<RAM :運行內存 ROM:SD卡>

內存泄漏 / 內存溢出

Exc_BAD_ACESS野指針(錯誤的內存訪問 )

/*
(a 向一個已經釋放的對象發送消息)
(b weak)
(c 指針)
檢測方法: 打開殭屍斷點
Edit Scheme-> Run->Diagnostics->Memory Management 
->Malloc Scribble (Bugly 函數 )(增大野指針的崩潰率)
-> Zombie Objects 殭屍對象
*/

 

1.需求分析:UIViewController是否釋放,pop/push

2.思路分析:

①ViewWillAppear / DidDisAppear

②肯定對象是否存活

1.靜態檢測方法

     手動:選中Xcode -> Product -> Analyze 【Shift +Command + B】

     自動檢測:Build-settings 搜索 Analyze

     Analyze During ‘Build’  設置爲YES

 

2.動態檢測方法  Instruments->Leaks

   1.跟蹤收集信息

     2.分析信息,定位問題

     3.定位問題,解決問題

   分析在繪製過程當中捕獲的數據。修復源代碼中的任何問題

    建議:Instruments 每次修改代碼切記使用 cmd + I 進行profile記錄

    內存泄漏檢查 常見的內存問題(內存泄露、野指針、殭屍對象、循環引用

   Xcode - > Open Developer Tool -> Instruments -Leaks 

   循環引用:精確到類名

    Leaks -> Cycles & Roots >Leak Cycles

3.第三方檢測工具

    pod ‘MLeaksFinder’, ‘~> 1.0.0’

 思路:

/*
UIViewController 延遲發送消息 
push ->viewWillAppear: NO
pop -> YES
viewDidDisappear: 標識信息,發送消息
*/
相關文章
相關標籤/搜索