為什么要做包體積優(yōu)化
隨著應用的不斷更新迭代,應用安裝包的體積會越來越大,用戶下載應用消耗流量產(chǎn)生的資費就會進一步增長,會導致用戶下載意愿會相對下降。
隨著包體積的不斷增大,安裝應用的時間變長會影響用戶的使用感受,對于內(nèi)存比較小的低端機型來說,應用解壓后內(nèi)存占用更大也會影響用戶的使用。
蘋果對iOS APP 大小有嚴格的限制,雖然蘋果官方也一直在提高可執(zhí)行文件的上限,在iOS13 還取消了強制的OTA限制,但是下載大小超過200MB的會默認請求用戶下載許可,并且在iOS13以下的設備依然會受到OTA的限制,影響新用戶轉(zhuǎn)化和老用戶的更新。
蘋果對可執(zhí)行文件大小有明確的限制,超過該限制可能會APP審核被拒。
具體的限制如下:
1、iOS7 之前,二進制文件中所有的__TEXT段總和不得超過80MB
2、iOS7.x - iOS 8.x,二進制文件中,每個特定架構(gòu)中的__TEXT段不得超過60MB
3、iOS9 之后,二進制文件中所有的__TEXT段總和不得超過500MB
所以,為了更好的用戶體驗和減少用戶等待的時間,包體積優(yōu)化都是APP優(yōu)化中非常重要的一環(huán)。
IPA安裝包分析
相關(guān)知識
【APP原始包體積】:上傳前ipa解包后,實際App的大小
【下載大小】:App壓縮包(.ipa文件)所占用的空間,用戶在App Store下載應用時下載的是壓縮包,這么做可以節(jié)省流量。
【安裝大小】:當壓縮包下載完成之后就會自動解壓(這個解壓過程也就是我們看到的安裝過程),安裝大小就是指壓縮包解壓之后所占用的空間。
【APP原始包體積】:
【下載大小】:
【安裝大小】:
安裝大小和下載大小是如何生成的
App的ipa包上傳到蘋果后臺后,蘋果會對上傳的ipa包解包后,對二進制進行了DRM加密(這個加密過程會導致包體積增大)和App Thinning,App Thinning會根據(jù)不同的機型對原始包的資源和代碼進行不同程度的裁剪,從而生成適配具體機型的版本,下圖是借用網(wǎng)友整理的一張圖來描述iOS APP的包的生成過程:
安裝包的構(gòu)成
松果出行安裝包現(xiàn)狀分析
包體積的優(yōu)化方案
Xcode編譯設置
一般這一步比較容易被忽略,因為提到優(yōu)化大家最先想到的就是資源優(yōu)化,比如:圖片壓縮、無用代碼刪除等,對Xcode自身的編譯優(yōu)化提及的反而不多,而且有的設置需要針對與實際項目結(jié)合起來才可以,比如:去掉斷點調(diào)試、異常支持等。
Build Settings去掉異常支持
Build Settings -> Architectures設置
Architetures 可以指定工程被編譯成可支持哪些指令集類型,支持的指令集越多就會編譯出越多個指令集的代碼包,也就會導致ipa包變大,默認的standrad architetures(armv7,arm64)參數(shù)打的包里面有32位、64位兩份指令集,根據(jù)是否需要32位來選擇是否更改指令集。
修改設置后,ipa包體積大小變化:78.1MB -> 55.1MB
Build Settings不生成調(diào)試符號
Build Settings -> Development PostProcessing設置
Build Settings -> Make Strings Read-Only設置為YES(默認)
Build Settings -> Dead Code Stripping設置為YES(默認)
Pod優(yōu)化
如果項目是OC但是使用了Swift三方庫,可以針對單個Swift庫使用 use_frameworks!而不是全部第三方庫都使用。
在OC項目中使用Swift庫 直接使用use_frameworks!會導致Pod中所有的庫都會打成動態(tài)庫,以及Swift和OC庫的依賴問題會導致依賴庫增加從而造成ipa包體積增大。
Asset Catalog Compiler編譯設置優(yōu)化
Xcode內(nèi)置的actool使用打壓縮算法包括: lzfse、 palette_img、 deepmap2、 deepmap_lzfse、zip,具體使用哪種算法跟iOS系統(tǒng)版本、Asset Catalog Compiler 中Optimization配置有關(guān)。
iOS 11.x:對應算法是 lzfse、zip
iOS 12.x - iOS 12.4.x:對應算法是 deepmap_lzfse、palette_img
iOS 13.x:對應算法是 deepmap2
注意:CocoaPods管理庫中的Assets catalog的編譯過程在CocoaPods生成的Copy Pods Resources這個腳本里面,所以上面的設置對Pod庫組件無效。
Build Settings -> Optimization Level 改為-Oz
Optimization Level默認為-Os,-Oz是Xcode 11之后才出現(xiàn)的編譯優(yōu)化選項,核心原理是對重復的連續(xù)機器指令外聯(lián)成函數(shù)進行復用,因此開啟Oz,能減少二進制的大小,但同時會帶來執(zhí)行效率的額外消耗。
Build Settings -> Link-Time Optimization設置為Incremental
蘋果在2016年的WWDC What’s new in LLVM 中詳細介紹了這個功能,LTO能帶來的優(yōu)化有:
將一些函數(shù)內(nèi)聯(lián)化:不用進行調(diào)用函數(shù)前的壓棧、調(diào)用函數(shù)后的出棧操作,提高運行效率和棧空間的利用率。
去除一些無用代碼
對程序有全局的優(yōu)化作用:比如if方法下的某個分支永遠不會執(zhí)行,那么在生成的二進制文件里面就不應該包含這部分代碼。
另外蘋果還稱LTO對app的運行速度也有正向的幫助,但是會降低LTO的編譯鏈接的速度,因此只建議在打正式包時設置改選項,同時也會導致link map的可讀性明顯降低。
Build Settings -> Enable On Demand Resources設置為YES(默認)
Xcode編譯設置優(yōu)化總結(jié)
資源文件優(yōu)化
資源文件的優(yōu)化是需要持續(xù)進行的,在前面咱們提到的Xcode編譯優(yōu)化設置配置好之后后續(xù)的開發(fā)只要不修改配置不需要過分關(guān)注。但是資源文件優(yōu)化不同,隨著項目的不斷更新迭代會不斷引入新的資源文件,同時也會不斷有廢棄資源的文件產(chǎn)生,因此資源優(yōu)化是要持續(xù)進行的。
資源文件的優(yōu)化分為兩步:無用資源的刪除 和 已用資源的壓縮。
無用資源的刪除
圖片資源的清理
使用【LSUnusedResources】工具檢測沒有用到的圖片資源,確認后進行刪除。
重復資源的引入
檢查項目中是否有功能類似的SDK,建議只保留一個,另外有些三方庫引入時可以只引入實際使用的部分不需要全量引入。
使用【fdupes】工具進行重復文件的掃描,僅保留一份即可。
fdupes工具的安裝和使用:
brew install fdupes
fdupes -Sr /Users/sunny/Desktop/TTPinecone > /Users/sunny/Desktop/fdupesResult.txt
未用到的類、方法的清理
已用資源的壓縮
項目中引入的圖片、網(wǎng)頁、json、音頻等文件的壓縮,這里主要了解一下圖片的壓縮。
Build Settings -> Compress PNG Files 設置為 YES (默認)
表示打包的時候自動對圖片進行無損壓縮。
注意:該選項對Assets中的資源無效 只對零散的資源文件。
Build Settings -> Remove Text Metadata From PNG Files 設置為****YES (默認)
表示移除PNG資源的文本字符。
resources
把資源文件都打包直接copy到framework的根目錄下。
注意:如果Pod里面沒有使用use_frameworks!不會生成對應的Framework的,則是直接把資源文件copy到app的根目錄下。
resource_bundles
CocoaPods 官方強烈建議使用resource_bundles,這樣可以避免相同名稱資源的名稱沖突,使用resource_bundles會為指定的資源打一個.bundle資源包。
單色圖標、功能簡單的圖標可以使用IconFont矢量圖標庫的方式
普通圖片可以使用 tinypng來進行壓縮
盡量使用xcassets來存放圖片資源
放入xcassets的2x和3x圖片在上傳時會根據(jù)具體設備分開對應分辨率的圖片,不會同時包含。而放入.bundle中的都會包含,所以建議把圖片放在xcassets里面管理。
注意:
- Assets.car在編譯過程中會選擇一些小圖片拼湊成一張大圖來提高圖片的加載效率,被放進這張大圖的小圖會通過偏移量的引用。建議使用頻率高且小的圖片放到Assets.car里面,Assets.car能保證加載和渲染速度最優(yōu)。
- 大圖(大于100KB的圖片)就不要放到Assets里面,考慮使用WebP格式,這個格式可以將圖片壓縮到最小。但是WebP在CPU消耗和解碼上是PNG的2倍,所以我們需要在性能和體積上做取舍。
Xcode中關(guān)于圖片壓縮的設置
有時候壓縮了圖片發(fā)現(xiàn)ipa包并沒有改變太多,原因大概是:
因為Xcode的Compress PNG Files選項的原因,建議如果自己壓縮圖片就把該項設置設置為NO。
Xcode 在構(gòu)建過程中有一個步驟叫compile assets catalog,Xcode會用自己的算法自行對png做圖片壓縮,并且會壓縮成能夠快速讀取渲染的格式。
資源文件優(yōu)化總結(jié)
優(yōu)化總結(jié)
是不是項目變大了做包體積優(yōu)化才有意義?
絕對不是,包體積優(yōu)化應該是一種習慣而不是等到包體積變得很大了才去思考做優(yōu)化,應該是只要覺得有優(yōu)化的空間就去做優(yōu)化。
如果打出來的ipa包比較小,說明我們的歷史負擔不嚴重,俗話說船小好掉頭而且編譯的速度也快,試錯成本也低,恰恰才是該優(yōu)化的時候,優(yōu)化總結(jié)出來的教訓落地到文檔形成一種規(guī)范,后續(xù)開發(fā)時也能時刻引起注意,這樣對于開發(fā)來說是最好的。
更多技術(shù)文章歡迎移步Sunny的個人技術(shù)博客。