<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          iOS 性能優(yōu)化那些繁雜瑣碎的事兒

          共 7845字,需瀏覽 16分鐘

           ·

          2022-03-05 15:40

          ????關(guān)注后回復(fù) “進(jìn)群” ,拉你進(jìn)程序員交流群????


          簡介

          這篇文章文章主要介紹iOS性能優(yōu)化方面的信息,主要從四個方面進(jìn)行:應(yīng)用啟動時間;頁面刷新滾動流暢度;耗電量;安裝包的大小

          • 應(yīng)用啟動時間

          • 頁面刷新滾動流暢度

          • 耗電量

          • 安裝包的大小

          1. 應(yīng)用啟動時間

          這里的應(yīng)用啟動時間指,應(yīng)用啟動到顯示第一個頁面展示時的時間。

          應(yīng)用啟動有冷啟動和熱啟動,熱啟動是指應(yīng)用在后臺活著,然后再啟動應(yīng)用。這里只談冷啟動。

          啟動時間在小于400ms是最佳的,因為從點(diǎn)擊圖標(biāo)到顯示Launch Screen,到Launch Screen消失這段時間是400ms。啟動時間不可以大于20s,否則會被系統(tǒng)殺掉。

          先來看看Xcode9新加的神器,通過添加環(huán)境變量可以打印出APP的啟動時間分析(Edit scheme -> Run -> Arguments),DYLD_PRINT_STATISTICS設(shè)置為1,如果查看更詳細(xì)的信息可以DYLD_PRINT_STATISTICS_DETAILS設(shè)置為1。

          然后啟動應(yīng)用,即可查看到以下信息

          Total pre-main time: 588.23 milliseconds (100.0%)         dylib loading time: 264.36 milliseconds (44.9%)        rebase/binding time:  56.19 milliseconds (9.5%)            ObjC setup time:  49.84 milliseconds (8.4%)           initializer time: 217.71 milliseconds (37.0%)           slowest intializers :             libSystem.B.dylib :   9.18 milliseconds (1.5%)    libMainThreadChecker.dylib :  36.42 milliseconds (6.1%)          libglInterpose.dylib :  82.35 milliseconds (14.0%)         libMTLInterpose.dylib :  32.51 milliseconds (5.5%)                         MeeYi :  24.89 milliseconds (4.2%)                   

          可以看到,在執(zhí)行main函數(shù)前,應(yīng)用準(zhǔn)備了執(zhí)行了4個流程:dylib loading、rebase/binding、ObjC setup、initializer,下面我們將好好分析這幾個流程。

          • load dylibs:加載動態(tài)庫,包括系統(tǒng)的、自己添加的(第三方的),遞歸一層一層加載所依賴的庫。

          • Rebase&Bind:修復(fù)指針,mach-o內(nèi)部的存儲邏輯是,信息的存儲地址是虛擬內(nèi)存,不是直接對應(yīng)物理內(nèi)存;每一次應(yīng)用啟動的時候,內(nèi)存的開始地址又是隨機(jī)的,因此需要對接虛擬內(nèi)存和物理內(nèi)存地址。為了安全,防止黑客攻擊。

          • Objc:注冊類信息到全局Table中

          • Initializers:初始化部分,+load方法初始化,C/C++靜態(tài)初始化對象和標(biāo)記__attribute__(constructor)的方法

          • Main() :執(zhí)行main函數(shù),執(zhí)行APPDelegate的方法

          • 加載Window+加載RootViewController+初始化操作:主要在didFinishLaunchingWithOptions執(zhí)行操作,比如初始化第三方庫,初始化基礎(chǔ)信息,加載RootViewController等

          在了解了應(yīng)用啟動流程后,那對應(yīng)用啟動優(yōu)化的工作就細(xì)分到了對每個流程的優(yōu)化上。

          1.1 main()函數(shù)之前:

          1.1.1 dylibs:加載動態(tài)庫

          啟動的第一步是加載動態(tài)庫,加載系統(tǒng)的動態(tài)庫是很快的,因為可以緩存,而加載內(nèi)嵌的動態(tài)庫速度較慢。

          所以,提高這一步的效率的關(guān)鍵是:減少動態(tài)庫的數(shù)量。合并動態(tài)庫。

          比如公司內(nèi)部由私有Pod建立了如下動態(tài)庫:XXTableView, XXHUD, XXLabel,強(qiáng)烈建議合并成一個XXUIKit來提高加載速度。

          1.1.2 Rebase & Bind & Objective C Runtime

          Rebase和Bind都是為了解決指針引用的問題。對于Objective C開發(fā)來說,主要的時間消耗在Class/Method的符號加載上,所以常見的優(yōu)化方案是:

          1)減少__DATA段中的指針數(shù)量。

          2)合并Category和功能類似的類。比如:UIView+Frame,UIView+AutoLayout…合并為一個

          刪除無用的方法和類。

          3)多用Swift Structs,因為Swfit Structs是靜態(tài)分發(fā)的。

          1.1.3 Initializers

          通常,我們會在+load方法中進(jìn)行method-swizzling,但這會影響應(yīng)用啟動的時間。

          1)用initialize替代load。不少同學(xué)喜歡用method-swizzling來實現(xiàn)AOP去做日志統(tǒng)計等內(nèi)容,強(qiáng)烈建議改為在initialize進(jìn)行初始化。

          2)減少atribute((constructor))的使用,而是在第一次訪問的時候才用dispatch_once等方式初始化。

          3)不要創(chuàng)建線程

          4)使用Swfit重寫代碼。

          1.2 main()函數(shù)之后:

          優(yōu)化的核心思想:能延遲初始化的盡量延遲初始化,不能延遲初始化的盡量放到后臺初始化。

          我們首先來分析下,從main函數(shù)開始執(zhí)行,到你的第一個界面顯示,這期間一般會做哪些事情。

          • 執(zhí)行AppDelegate的代理方法,主要是didFinishLaunchingWithOptions,applicationDidBecomeActive,

          • 初始化第三方skd

          • 初始化Window,初始化基礎(chǔ)的ViewController

          • 獲取數(shù)據(jù)(Local DB/Network),展示給用戶。

          在這個過程中我們可以借助工具來進(jìn)行檢測

          • 知道這個過程后,可以借助Time Profiler工具查找具體的耗時模塊,幾點(diǎn)要注意:

            • 分析啟動時間,一般只關(guān)心主線程

            •  選擇Hide System Libraries和Invert Call Tree,這樣我們能專注于自己的代碼

            •  右側(cè)可以看到詳細(xì)的調(diào)用堆棧信息

          • 另外,也可以借用C語言函數(shù)查看模塊運(yùn)行時間:

          CFTimeInterval startTime = CACurrentMediaTime();//執(zhí)行方法CFTimeInterval endTime = CACurrentMediaTime();

          當(dāng)檢測出耗時的模塊時,就可以按照優(yōu)化的核心思想來進(jìn)行處理了。即:

          能延遲初始化的盡量延遲初始化,不能延遲初始化的盡量放到后臺初始化。

          2. 頁面刷新滾動流暢度

          在優(yōu)化流程度前需要先了解下iOS頁面的成像過程。

          2.1 CPU(Central Processing Unit,中央處理器):

          對象的創(chuàng)建和銷毀、對象屬性的調(diào)整、布局計算、文本的計算和排版、圖片的格式轉(zhuǎn)換和解碼、圖像的繪制(Core Graphics)

          2.2 GPU(Graphics Processing Unit,圖形處理器):

          紋理的渲染

          2.3 成像過程:

          CPU計算信息,GPU渲染信息到幀緩存區(qū)(iOS是雙緩存機(jī)制,有前幀緩存、后幀緩存),視頻控制器從幀緩存中讀取信息顯示到屏幕上。

          2.4 造成卡頓的原因:

          按照60FPS的刷幀率,每隔16ms就會有一次VSync信號,VSync信號來的時候就需要從幀緩存區(qū)中取緩存顯示到屏幕上,如果每次VSync信號來的時候CPU和GPU沒有處理好信息渲染到緩存區(qū),那么就會從緩存中拿之前緩存的顯示,就造成了丟幀,丟幀多了就會造成卡頓。

          2.5 檢測卡頓

          平時所說的“卡頓”主要是因為在主線程執(zhí)行了比較耗時的操作,這里檢測的有兩個方案:

          • Instruments中的coreAnimation工具,查看刷幀率,最理想最高的是60fps

          • 可以添加Observer到主線程RunLoop中,通過監(jiān)聽RunLoop狀態(tài)切換的耗時,以達(dá)到監(jiān)控卡頓的目的
            這個可以借助第三方框架(github上很多),如:LXDAppFluecyMonitor、JPFPSStatus

          2.6 解決卡頓

          盡可能減少CPU、GPU資源消耗

          2.6.1 優(yōu)化

          • 優(yōu)化CPU

            • 盡量用輕量級的對象,比如用不到事件處理的地方,可以考慮使用CALayer取代UIView

            • 不要頻繁地調(diào)用UIView的相關(guān)屬性,比如frame、bounds、transform等屬性,盡量減少不必要的修改

            • 盡量提前計算好布局,在有需要時一次性調(diào)整對應(yīng)的屬性,不要多次修改屬性

            • Autolayout會比直接設(shè)置frame消耗更多的CPU資源

            • 圖片的size最好剛好跟UIImageView的size保持一致

            • 控制一下線程的最大并發(fā)數(shù)量

            • 盡量把耗時的操作放到子線程:如文本處理(尺寸計算、繪制);圖片處理(解碼、繪制)

          • 優(yōu)化GPU

            • 盡量避免短時間內(nèi)大量圖片的顯示,盡可能將多張圖片合成一張進(jìn)行顯示

            • 盡量減少視圖數(shù)量和層次

            • 減少透明的視圖(alpha<1),不透明的就設(shè)置opaque為YES

            • 盡量避免出現(xiàn)離屏渲染

          • 避免離屏渲染

          在OpenGL中,GPU有2種渲染方式:

            • On-Screen Rendering:當(dāng)前屏幕渲染,在當(dāng)前用于顯示的屏幕緩沖區(qū)進(jìn)行渲染操作;

            • Off-Screen Rendering:離屏渲染,在當(dāng)前屏幕緩沖區(qū)以外新開辟一個緩沖區(qū)進(jìn)行渲染操作


            • 離屏渲染消耗性能的原因

            • 需要創(chuàng)建新的緩沖區(qū)

            • 離屏渲染的整個過程,需要多次切換上下文環(huán)境,先是從當(dāng)前屏幕(On-Screen)切換到離屏(Off-Screen);等到離屏渲染結(jié)束以后,將離屏緩沖區(qū)的渲染結(jié)果顯示到屏幕上,又需要將上下文環(huán)境從離屏切換到當(dāng)前屏幕


            • 會造成離屏渲染的有:

            • 光柵化,layer.shouldRasterize = YES

            • 遮罩,layer.mask

            • 圓角,同時設(shè)置layer.masksToBounds = YES、layer.cornerRadius大于(考慮通過CoreGraphics繪制裁剪圓角,或者叫美工提供圓角圖片)

            • 陰影,layer.shadowXXX,如果設(shè)置了layer.shadowPath就不會產(chǎn)生離屏渲染

          3. 耗電量

          3.1 應(yīng)用耗電的主要來源有:

          • CPU處理,Processing

          • 網(wǎng)絡(luò),Networking

          • 定位,Location

          • 圖像,Graphics

          3.2 耗電優(yōu)化:

          • 盡可能降低CPU、GPU功耗

          • 少用定時器

          • 優(yōu)化I/O操作

            • 盡量不要頻繁寫入小數(shù)據(jù),最好批量一次性寫入

            • 讀寫大量重要數(shù)據(jù)時,考慮用dispatch_io,其提供了基于GCD的異步操作文件I/O的API。用dispatch_io系統(tǒng)會優(yōu)化磁盤訪問

            • 數(shù)據(jù)量比較大的,建議使用數(shù)據(jù)庫(比如SQLite、CoreData)

          • 網(wǎng)絡(luò)優(yōu)化

            • 減少、壓縮網(wǎng)絡(luò)數(shù)據(jù)

            • 如果多次請求的結(jié)果是相同的,盡量使用緩存

            • 使用斷點(diǎn)續(xù)傳,否則網(wǎng)絡(luò)不穩(wěn)定時可能多次傳輸相同的內(nèi)容

            • 網(wǎng)絡(luò)不可用時,不要嘗試執(zhí)行網(wǎng)絡(luò)請求

            • 讓用戶可以取消長時間運(yùn)行或者速度很慢的網(wǎng)絡(luò)操作,設(shè)置合適的超時時間

            • 批量傳輸,比如,下載視頻流時,不要傳輸很小的數(shù)據(jù)包,直接下載整個文件或者一大塊一大塊地下載。如果下載廣告,一次性多下載一些,然后再慢慢展示。如果下載電子郵件,一次下載多封,不要一封一封地下載

          • 定位優(yōu)化

            • 如果只是需要快速確定用戶位置,最好用CLLocationManager的requestLocation方法。定位完成后,會自動讓定位硬件斷電

            • 如果不是導(dǎo)航應(yīng)用,盡量不要實時更新位置,定位完畢就關(guān)掉定位服務(wù)

            • 盡量降低定位精度,比如盡量不要使用精度最高的kCLLocationAccuracyBest

            • 需要后臺定位時,盡量設(shè)置pausesLocationUpdatesAutomatically為YES,如果用戶不太可能移動的時候系統(tǒng)會自動暫停位置更新

            • 盡量不要使用startMonitoringSignificantLocationChanges,優(yōu)先考慮startMonitoringForRegion:

          • 硬件檢測優(yōu)化

            • 用戶移動、搖晃、傾斜設(shè)備時,會產(chǎn)生動作(motion)事件,這些事件由加速度計、陀螺儀、磁力計等硬件檢測。在不需要檢測的場合,應(yīng)該及時關(guān)閉這些硬件

            4. 安裝包瘦身

            安裝包(IPA)主要由可執(zhí)行文件、資源組成,因此對于iOS安裝包的瘦身也將從這兩個方面進(jìn)行

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

            • 采取無損壓縮

            • 去除沒有用到的資源

            4.2 可執(zhí)行文件瘦身

            • 編譯器優(yōu)化

              • Strip Linked Product、Make Strings Read-Only、Symbols Hidden by Default設(shè)置為YES

              • 去掉異常支持,Enable C++ Exceptions、Enable Objective-C Exceptions設(shè)置為NO, Other C Flags添加-fno-exceptions

            • 利用AppCode(www.jetbrains.com/objc/)檢測未使用的代碼:菜單欄 -> Code -> Inspect Code

            • 編寫LLVM插件檢測出重復(fù)代碼、未被調(diào)用的代碼

            • 生成LinkMap文件,可以查看可執(zhí)行文件的具體組成,哪些文件偏大

              • 可借助第三方工具解析LinkMap文件:github.com/huanxsd/Lin…

              4.3 bitcode

              xcode7之后多了這樣的一個設(shè)置,默認(rèn)是打開的。打開bitcode設(shè)置后,編譯出來的包不是最終的二進(jìn)制包而是bitcode中間碼,Apple會根據(jù)編譯器、應(yīng)用設(shè)備來優(yōu)化bitcode來給你最終最最優(yōu)化的二進(jìn)制應(yīng)用包。這樣避免了蘋果更新了編譯器或硬件設(shè)備時再提交app包到appstore的問題。同時也享受到了編譯器改進(jìn)帶來的好處。

              但是有個坑的地方,有些第三方庫并不支持bitcode,如果要使用對應(yīng)的第三方庫就得關(guān)閉這個bitcode。由于時間太久,已經(jīng)忘了當(dāng)時是哪些第三方庫不支持了,不知道現(xiàn)在有沒有支持。

              5. 其他:

              • Facebook 和 Pinterest 維護(hù)的 ASDK 可對視圖的渲染進(jìn)行優(yōu)化,具體可參考這篇博客

              • 網(wǎng)絡(luò)請求優(yōu)化:

                • 網(wǎng)絡(luò)請求數(shù)據(jù)緩存:針對于時效性比較長的可以做緩存,在請求的時候在有效期內(nèi)直接獲取此信息

                • 網(wǎng)絡(luò)請求次數(shù)優(yōu)化:請求開始、取消、回調(diào)之前做限制-------AOP面向切片編程


              青山不改,綠水長流,感謝大家支持,希望這篇文章能幫助到你??!


              轉(zhuǎn)自:掘金-會飛的金魚

              鏈接:https://juejin.cn/post/7056447904189251598

              -End-

              最近有一些小伙伴,讓我?guī)兔φ乙恍?nbsp;面試題 資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來,可以說是程序員面試必備!所有資料都整理到網(wǎng)盤了,歡迎下載!

              點(diǎn)擊??卡片,關(guān)注后回復(fù)【面試題】即可獲取

              在看點(diǎn)這里好文分享給更多人↓↓

              瀏覽 43
              點(diǎn)贊
              評論
              收藏
              分享

              手機(jī)掃一掃分享

              分享
              舉報
              評論
              圖片
              表情
              推薦
              點(diǎn)贊
              評論
              收藏
              分享

              手機(jī)掃一掃分享

              分享
              舉報
              <kbd id="afajh"><form id="afajh"></form></kbd>
              <strong id="afajh"><dl id="afajh"></dl></strong>
                <del id="afajh"><form id="afajh"></form></del>
                    1. <th id="afajh"><progress id="afajh"></progress></th>
                      <b id="afajh"><abbr id="afajh"></abbr></b>
                      <th id="afajh"><progress id="afajh"></progress></th>
                      人人操美女 | 迷情校园综合 | 视频在线三区 | 久久久久黄色片 | 久草视频在线播放 |