性能優化

CPU和GPU

  • 在屏幕成像的過程當中,CPU和GPU起着相當重要的做用
    • CPU(Central Processing Unit,中央處理器)git

      • 對象的建立和銷燬、對象屬性的調整、佈局計算、文本的計算和排版、圖片的格式轉換和解碼、圖像的繪製(Core Graphics)
    • GPU(Graphics Processing Unit,圖形處理器)github

      • 紋理的渲染

image.png

  • 在iOS中是雙緩衝機制,有前幀緩存、後幀緩存

屏幕成像原理

image.png

卡頓產生的緣由

image.png

  • 卡頓解決的主要思路
    • 儘量減小CPU、GPU資源消耗
  • 按照60FPS的刷幀率,每隔16ms就會有一次VSync信號

卡頓優化 - CPU

  • 儘可能用輕量級的對象,好比用不到事件處理的地方,能夠考慮使用CALayer取代UIView
  • 不要頻繁地調用UIView的相關屬性,好比frame、bounds、transform等屬性,儘可能減小沒必要要的修改
  • 儘可能提早計算好佈局,在有須要時一次性調整對應的屬性,不要屢次修改屬性
  • Autolayout會比直接設置frame消耗更多的CPU資源
  • 圖片的size最好恰好跟UIImageView的size保持一致
  • 控制一下線程的最大併發數量
  • 儘可能把耗時的操做放到子線程
    • 文本處理(尺寸計算、繪製)
    • 圖片處理(解碼、繪製)
  • 儘可能避免短期內大量圖片的顯示,儘量將多張圖片合成一張進行顯示
  • GPU能處理的最大紋理尺寸是4096x4096,一旦超過這個尺寸,就會佔用CPU資源進行處理,因此紋理儘可能不要超過這個尺寸
  • 儘可能減小視圖數量和層次
  • 減小透明的視圖(alpha<1),不透明的就設置opaque爲YES
  • 儘可能避免出現離屏渲染

離屏渲染

  • 在OpenGL中,GPU有2種渲染方式
    • On-Screen Rendering:當前屏幕渲染,在當前用於顯示的屏幕緩衝區進行渲染操做
    • Off-Screen Rendering:離屏渲染,在當前屏幕緩衝區之外新開闢一個緩衝區進行渲染操做
  • 離屏渲染消耗性能的緣由
    • 須要建立新的緩衝區
    • 離屏渲染的整個過程,須要屢次切換上下文環境,先是從當前屏幕(On-Screen)切換到離屏(Off-Screen);等到離屏渲染結束之後,將離屏緩衝區的渲染結果顯示到屏幕上,又須要將上下文環境從離屏切換到當前屏幕
  • 哪些操做會觸發離屏渲染?
    • 光柵化,layer.shouldRasterize = YES數據庫

    • 遮罩,layer.mask緩存

    • 圓角,同時設置layer.masksToBounds = YES、layer.cornerRadius大於0markdown

      • 考慮經過CoreGraphics繪製裁剪圓角,或者叫美工提供圓角圖片
    • 陰影,layer.shadowXXX網絡

      • 若是設置了layer.shadowPath就不會產生離屏渲染

卡頓檢測

  • 平時所說的「卡頓」主要是由於在主線程執行了比較耗時的操做
  • 能夠添加Observer到主線程RunLoop中,經過監聽RunLoop狀態切換的耗時,以達到監控卡頓的目的

耗電的主要來源

image.png

  • CPU處理,Processing
  • 網絡,Networking
  • 定位,Location
  • 圖像,Graphics

耗電優化

  • 儘量下降CPU、GPU功耗併發

  • 少用定時器app

  • 優化I/O操做異步

    • 儘可能不要頻繁寫入小數據,最好批量一次性寫入
    • 讀寫大量重要數據時,考慮用dispatch_io,其提供了基於GCD的異步操做文件I/O的API。用dispatch_io系統會優化磁盤訪問
    • 數據量比較大的,建議使用數據庫(好比SQLite、CoreData)
  • 網絡優化函數

    • 減小、壓縮網絡數據
    • 若是屢次請求的結果是相同的,儘可能使用緩存
    • 使用斷點續傳,不然網絡不穩定時可能屢次傳輸相同的內容
    • 網絡不可用時,不要嘗試執行網絡請求
    • 讓用戶能夠取消長時間運行或者速度很慢的網絡操做,設置合適的超時時間
    • 批量傳輸,好比,下載視頻流時,不要傳輸很小的數據包,直接下載整個文件或者一大塊一大塊地下載。若是下載廣告,一次性多下載一些,而後再慢慢展現。若是下載電子郵件,一次下載多封,不要一封一封地下載
  • 定位優化

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

    • 用戶移動、搖晃、傾斜設備時,會產生動做(motion)事件,這些事件由加速度計、陀螺儀、磁力計等硬件檢測。在不須要檢測的場合,應該及時關閉這些硬件

APP的啓動

  • APP的啓動能夠分爲2種

    • 冷啓動(Cold Launch):從零開始啓動APP
    • 熱啓動(Warm Launch):APP已經在內存中,在後臺存活着,再次點擊圖標啓動APP
  • APP啓動時間的優化,主要是針對冷啓動進行優化

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

    • DYLD_PRINT_STATISTICS設置爲1
    • 若是須要更詳細的信息,那就將DYLD_PRINT_STATISTICS_DETAILS設置爲1

image.png

image.png

  • 如圖顯示
    • pre-main time : 調用main函數以前調用的時間
    • dylib loading time :動態庫加載
    • rebase/binding time :
    • objC setup time: 結構體準備時間
    • initializer time : 初始化耗時
    • slowest intializers : 加載比較忙的庫
      • libsystem.dylib
      • libMainThreadChecker.dylib
  • 更加詳細的打印

image.png

  • 少於400毫秒都是能夠接受的

image.png

  • APP的冷啓動能夠歸納爲3大階段
    • dyld
    • runtime
    • main

image.png

APP的啓動 - dyld

  • dyld(dynamic link editor),Apple的動態連接器,能夠用來裝載Mach-O文件(可執行文件、動態庫等)
  • 啓動APP時,dyld所作的事情有
    • 裝載APP的可執行文件Mach-o文件,同時會遞歸加載全部依賴的動態庫
    • 當dyld把可執行文件、動態庫都裝載完畢後,會通知Runtime進行下一步的處理

APP的啓動 - runtime

  • 啓動APP時,runtime所作的事情有

    • 調用map_images進行可執行文件內容的解析和處理
    • 在load_images中調用call_load_methods,調用全部Class和Category的+load方法
    • 進行各類objc結構的初始化(註冊Objc類 、初始化類對象等等)
    • 調用C++靜態初始化器和__attribute__((constructor))修飾的函數
  • 到此爲止,可執行文件和動態庫中全部的符號(Class,Protocol,Selector,IMP,…)都已經按格式成功加載到內存中,被runtime 所管理

APP的啓動 - main

  • 總結一下
    • APP的啓動由dyld主導,將可執行文件加載到內存,順便加載全部依賴的動態庫
    • 並由runtime負責加載成objc定義的結構
    • 全部初始化工做結束後,dyld就會調用main函數
    • 接下來就是UIApplicationMain函數,AppDelegate的application:didFinishLaunchingWithOptions:方法

APP的啓動優化

  • 按照不一樣的階段
    • dyld

      • 減小動態庫、合併一些動態庫(按期清理沒必要要的動態庫)
      • 減小Objc類、分類的數量、減小Selector數量(按期清理沒必要要的類、分類)
      • 減小C++虛函數數量
      • Swift儘可能使用struct
    • runtime

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

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

安裝包瘦身

  • 安裝包(IPA)主要由可執行文件、資源組成

  • 資源(圖片、音頻、視頻等)

  • 可執行文件瘦身

    • 編譯器優化

      • Strip Linked Product、Make Strings Read-Only、Symbols Hidden by Default設置爲YES
      • 去掉異常支持,Enable C++ Exceptions、Enable Objective-C Exceptions設置爲NO, Other C Flags添加-fno-exceptions
    • 利用AppCode(www.jetbrains.com/objc/)檢測未使用… -> Code -> Inspect Code

    image.png

    • 編寫LLVM插件檢測出重複代碼、未被調用的代碼

LinkMap

  • 生成LinkMap文件,能夠查看可執行文件的具體組成

image.png

相關文章
相關標籤/搜索