OC項目編譯優(yōu)化

參考文章鏈接:關(guān)于Xcode編譯性能優(yōu)化的研究工作總結(jié)

一、編譯時長優(yōu)化Architectures

在Build Setting 中,有個Architectures配置選項。

Architectures: 是指定工程支持的指令集的集合,如果設(shè)置多個architecture,則生成的二進(jìn)制包會包含多個指令集代碼,提及會隨之變大。
Valid Architectures: 有效的指令集集合,Architectures與Valid Architectures的交集來確定最終的數(shù)據(jù)包含的指令集代碼。
Build Active Architecture Only :指定是否只對當(dāng)前連接設(shè)備所支持的指令集編譯,默認(rèn)Debug的時候設(shè)置為YES,Release的時候設(shè)為NO。Debug設(shè)置為YES時只編譯當(dāng)前的architecture版本,生成的包只包含當(dāng)前連接設(shè)備的指令集代碼;設(shè)置為NO時,則生成的包包含所有的指令集代碼(上述的Valid Architecture與Architectures的交集)。所以為了更快的編譯速度,Debug應(yīng)設(shè)為YES,而Release應(yīng)設(shè)為NO。

PS:Debug設(shè)置為YES時,如果連接的設(shè)備是arm64的(iPhone 5s,iPhone 6(plus)等),則Valid Architecture中必須包含arm64,否則編譯會出錯。這種模式下編譯出來的版本是向下兼容的,即:編譯出的armv6版本可在armv7版本上運行。

二、編譯時長優(yōu)化Precompile Prefix Header 預(yù)編譯頭文件

Xcode6以及之后版本默認(rèn)不適用PCH文件參與項目編譯,原因有二:

  • 去掉自動導(dǎo)入的系統(tǒng)框架類庫的頭文件可以提高源文件的復(fù)用性,便于遷移;
  • 一個龐大的Prefix Header 會增加Build耗時

但對于原項目應(yīng)用了PCH文件的情況,就需要對Xcode的Build Setting進(jìn)行配置以使用pch。

當(dāng)Precompile Prefix Header設(shè)為NO時,頭文件pch不會被預(yù)編譯,而是在每個用到它導(dǎo)入的框架類庫中編譯一次。每個引用了pch內(nèi)容的.m文件都要編譯一次pch,這會降低項目的編譯速度。

將Precompile Prefix Header設(shè)為YES時,pch文件會被預(yù)編譯,預(yù)編譯后的pch會被緩存起來,從而提高編譯速度。 需要編譯的pch文件在Prefix Header中注冊即可。

三、加載RAM磁盤編譯Xcode項目

DerivedData

Xcode會在文件系統(tǒng)中幾種緩存臨時信息。

每次對Xcode iOS項目進(jìn)行clean、build或者在iOS虛擬機上launch,Xcode都會在DeriveData文件夾中進(jìn)行讀寫操作。換句話說,就是將Derived Data的讀寫從硬盤移動到內(nèi)存中。

DeriveData文件夾中包含了所有的build信息、debug- 和 release- built targets以及項目的索引。當(dāng)遇到零散索引(odd index)問題(代碼塊補全工作不正常、經(jīng)常性的重建索引、或者運行項目緩慢)時,它可以有效地刪除衍生數(shù)據(jù)。刪除這個文件夾將會導(dǎo)致所有Xcode上的項目信息遭到破壞。

步驟1

將DeriveData下的文件刪除:

hdid -nomount ram://4194304  ```

刪除這些數(shù)據(jù),Xcode會在Build時重新寫入

*步驟2*

在~/Library/Developer/Xcode/DerivedData.上部署安裝2 GB大小的RAM磁盤。 進(jìn)到
~/Library/Developer/Xcode/DerivedData.

` cd ~/Library/Developer/Xcode/DerivedData`

創(chuàng)建2 GB的RAM磁盤(size的計算公式 size = 需要分配的空間(M) * 1024 * 1024 / 512):` hdid -nomount ram://4194304 `

此行命令后將會輸出RAM磁盤的驅(qū)動名字:/dev/diskN(N為數(shù)字)。

初始化磁盤:`newfs_hfs -v DerivedData /dev/rdiskN`

有以下輸出:    Initialized /dev/rdisk3 as a 2 GB case-insensitive HFS Plus volume

安裝磁盤:`diskutil mount -mountPoint ~/Library/Developer/Xcode/DerivedData /dev/diskN `

這會在已存在的DeriveData上安裝一個卷,用于隱藏舊的文件。這些文件仍會占據(jù)空間,但在移除RAM磁盤之前都無法訪問。
在重啟或從Finder中彈出RAM磁盤時,磁盤內(nèi)容會消失。下次再創(chuàng)建磁盤時,Xcode將會重新構(gòu)建它的索引和你的項目中的中間文件。
創(chuàng)建虛擬磁盤后,并不直接占用掉所有的分配空間,而是根據(jù)虛擬磁盤中的文件總大小來逐漸占用內(nèi)存。
注意:如果虛擬磁盤已滿,會導(dǎo)致編譯的失敗。此時清除掉DeriveData后zhong重新編譯,就算有足夠的空間也還是有可能會導(dǎo)致編譯失敗。重啟Xcode可以解決此問題。

### 四、編譯線程數(shù)和Debug Information Format

- **4.1、 提高XCode編譯時使用的線程數(shù)**

`defaults write com.apple.Xcode PBXNumberOfParallelBuildSubtasks 8 `
其后的數(shù)字為指定的編譯線程數(shù)。XCode默認(rèn)使用與CPU核數(shù)相同的線程來進(jìn)行編譯,但由于編譯過程中的IO操作往往比CPU運算要多,因此適當(dāng)?shù)奶嵘€程數(shù)可以在一定程度上加快編譯速度。

- **4.2、 將Debug Information Format改為DWARF**
在工程對應(yīng)Target的Build Settings中,找到Debug Information Format這一項,將Debug時的DWARF with dSYM file改為DWARF。
需要注意的是,將Debug Information Format改為DWARF之后,會導(dǎo)致在Debug窗口無法查看相關(guān)類類型的成員變量的值。當(dāng)需要查看這些值時,可以將Debug Information Format改回DWARF with dSYM file,clean(必須)之后重新編譯即可。

ps:4.2的解決方案為Xcode的默認(rèn)設(shè)置,進(jìn)行反向設(shè)置時,編譯速度改變不大;

### 五、Link-Time Optimizations 鏈接時優(yōu)化

Link-Time Optimization執(zhí)行鏈接時優(yōu)化(LTO)。在Clang/LLVM領(lǐng)域,這意味著鏈接器獲得的是LLVM字節(jié)碼,而不是通常的目標(biāo)文件。這些字節(jié)碼在一種更抽象的層次上代表程序這里寫鏈接內(nèi)容的執(zhí)行過程,允許LTO得以進(jìn)行,但是壞處是,仍然需要將他們轉(zhuǎn)換成機器代碼,在鏈接時需要額外的處理時間。

參數(shù)設(shè)為YES時,能夠優(yōu)化鏈接時間;目標(biāo)文件以LLVM二進(jìn)制文件格式存儲,在鏈接期間,優(yōu)化了整個程序。
將其設(shè)為NO時,可以減少Link階段的時間。對于Link階段耗時較長的項目,整體編譯優(yōu)化體現(xiàn)較為明顯。

### 六、加裝SSD固態(tài)硬盤

固態(tài)硬盤傳輸速度能達(dá)到500MB/s,其中讀取速度達(dá)到400-600MB每秒,寫入速度達(dá)到200MB每秒。而傳統(tǒng)硬盤讀取速度極限也無法超越200MB每秒,寫入速度在100MB每秒左右。如果遇到非連續(xù)的散片數(shù)據(jù),SSD能體現(xiàn)出極快的讀寫速度。而傳統(tǒng)機械硬盤由于磁頭尋道等原因,傳輸速度偏慢。

SSD加快了程序的I/O速率,讀寫速度比普通硬盤快,從而提升Xcode的編譯速度。

###七、安裝包大小優(yōu)化 Asset Catalog Compiler - Options Optimization
Build Setting->Asset Catelog Compiler -> Options

在Optimization優(yōu)化設(shè)置項有三個選項,不制定、time和Space

Optimization nothing是Xcode默認(rèn)的設(shè)置。 與預(yù)想的不同,在選擇Optimization time 時,編譯時長并沒有得到優(yōu)化。 但在Optimization space時,編譯耗時基本沒有波動,但編譯生成的app 大小有不小程度的優(yōu)化。

### 八、安裝包大小優(yōu)化 Flatten Compiles XIB Files
是否流暢編譯XIB文件

>指定是否在編譯時剝離storyBoard文件以優(yōu)化它們的大小,設(shè)為YES時編譯出來的文件會被壓縮,但是不能編輯。

### 九、安裝包大小優(yōu)化,清理未被使用的圖片資源

**LSUnusedResources**
 
項目的開發(fā)過程總是會經(jīng)歷較長期的迭代,不斷的添加功能的同時會引入大量的圖片資源。需求變更、業(yè)務(wù)邏輯修改等需要移除某些功能模塊時就會導(dǎo)致這些前期加入的圖片資源問價被忽略而遺留在編譯的安裝包中,長此以往會使得安裝包變得格外臃腫。特別是類似于手Q項目的開發(fā),開發(fā)人員多,產(chǎn)品迭代頻繁,開發(fā)時間緊俏,開發(fā)人員輪換等特點更有可能導(dǎo)致這樣的后果。

一個較為傳統(tǒng)的清理方法時將圖片資源的文件名一一復(fù)制粘貼到Xcode的全局變量查找中去查找該字符串,如果返回的結(jié)果為零,則該資源很有可能沒被使用。之所以是“很有可能”,是因為在代碼中,資源有時是通過字符串拼接的方式進(jìn)行引用的。

在這里提供一個github上的開源工具 LSUnusedResources ,這個工具是對github上的另一個開源工具Unused的優(yōu)化改進(jìn)(匹配速度、結(jié)果準(zhǔn)確性),作者針對源碼、Xib、Storyboard 和 plist 等文件,先全文搜索其中可能是引用了資源的字符串,然后用資源名和字符串做匹配,從而找出未被使用的資源,比Unused的查找速度要快得多。

使用起來也比較簡單:
 1、將工程目錄路徑拷貝到Folder或通過Browse瀏覽文件目錄;
 2、在Resource指定要查找的資源類型; (經(jīng)過本人測試,發(fā)現(xiàn)該工具在未指定Resource類型時所查找出來的資源不是很準(zhǔn)確,列舉出 的資源事實上是正在使用的,所以我在測試時指定查找了png類型的文件。) 
3、單擊Search以查閱結(jié)果。

注:為了避免對資源的誤刪操作,建議在該工具輸出結(jié)果后對結(jié)果中的資源名復(fù)制并在Xcode的全局查找
中進(jìn)行校驗。

下載安裝:[LSUnusedResources.app.zip](https://github.com/tinymind/LSUnusedResources/raw/master/Release/LSUnusedResources.app.zip)
 Github地址:[LSUnusedResources](https://github.com/tinymind/LSUnusedResources) 
參考鏈接:[查找XCode工程中沒被使用的圖片資源](http://blog.csdn.net/qq_25131687/article/details/blog.lessfun.com/blog/2015/09/02/find-unused-resources-in-xcode-project/)

### 十、安裝包大小優(yōu)化Deployment Postprocessing和Strip Linked Product

Xcode中Strip Linked Product 的默認(rèn)設(shè)置為YES,但是Deployment Postprocessing的默認(rèn)設(shè)置為NO。在Deployment Postprocessing 是Deployment的總開關(guān),所以在打開這個選項之前 Strip Linked Product是不起作用的。

ps:當(dāng)Strip Linked Product設(shè)為YES的時候,運行app,斷點不會中斷,在程序中打印`[NSThread callStackSymbols]`也無法看到類名和方法名。而在程序崩潰時,函數(shù)調(diào)用棧中也無法看到類名和方法名。

打開這兩個選項之后進(jìn)行編譯,編譯出的安裝包有了較大程度的優(yōu)化。

### 十一、安裝包大小優(yōu)化 Linking->Dead Code Stripping

將Dead Code Stripping 設(shè)置為YES 也能夠一定程度上對程序安裝包進(jìn)行優(yōu)化,只是優(yōu)化的效果一般,對于一些比較小的項目甚至沒有什么優(yōu)化體現(xiàn),所以這里也就沒有上測試數(shù)據(jù)。

Dead Code Stripping 是對程序編譯出的可執(zhí)行二進(jìn)制文件中沒有被實際使用的代碼進(jìn)行Strip操作
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容