前言
包體積的問(wèn)題,尤其是作為第三方需要準(zhǔn)入某個(gè)體量比較大的app時(shí),通常有體積的要求,減少包體積的方式網(wǎng)上有不少文章,拋開減少資源文件和砍業(yè)務(wù)的方法,今天談一下還有兩個(gè)值得關(guān)注的編譯選項(xiàng):Enable Exceptions, Link-Time Optimazition.
Enable Exceptions
Xcode中有兩個(gè)關(guān)于異常捕獲的選項(xiàng),分別是Enable C++ Exceptions, Enable Objective-C Exceptions. 一般默認(rèn)都是開啟的。如果你想要在代碼中使用try catch,那么一定需要開啟這兩個(gè)選項(xiàng)。
基本上Objective-C/Swift項(xiàng)目都使用了ARC + LLVM,在LLVM的文檔中關(guān)于異常捕獲是這么說(shuō)的:
The standard Cocoa convention is that exceptions signal programmer error and are not intended to be recovered from. Making code exceptions-safe by default would impose severe runtime and code size penalties on code that typically does not actually care about exceptions safety. Therefore, ARC-generated code leaks by default on exceptions, which is just fine if the process is going to be immediately terminated anyway.
Google翻譯:
Cocoa的習(xí)慣就是當(dāng)遇到異常的時(shí)候并不打算鳥它。如果你并不關(guān)心你的破代碼是不是異常安全,支持異常捕獲會(huì)讓你的代碼運(yùn)行效率降低并且增加代碼體積。所以我們的處理是,當(dāng)遇到異常情況時(shí),ARC自己產(chǎn)生的代碼就會(huì)立即崩掉,我們覺得這樣挺好的。
所以如果你的項(xiàng)目不需要從異常中恢復(fù),那么按照文檔的說(shuō)法,關(guān)掉
Exception可以減少包體積并且增加運(yùn)行速度。
從我們的項(xiàng)目來(lái)看,因?yàn)槲覀冺?xiàng)目中只用了非常少量的try catch來(lái)處理一些異常,把這些代碼注釋掉并且關(guān)閉Enable C++ Exceptions, Enable Objective-C Exceptions這兩個(gè)選項(xiàng)之后,項(xiàng)目的linkmap體積減少了約140kb(基礎(chǔ)為3.7mb)。
那如果整個(gè)項(xiàng)目99%的代碼都不需要異常捕獲,單獨(dú)就幾個(gè)地方要,能不能單獨(dú)為整個(gè)文件開啟異常捕獲呢?理論上是可以的,在微信的文章中[1],提到可以單獨(dú)對(duì)文件設(shè)置-fexceptions來(lái)對(duì)某些文件單獨(dú)支持異常捕獲,不過(guò)我做來(lái)一些嘗試都沒(méi)有成功,Google上面也沒(méi)有多少相關(guān)的信息...如果有成功的同學(xué)請(qǐng)回復(fù)交流(捂臉哭)。
Link-Time Optimization
先介紹一下什么是Link-Time Optimization (LTO),原版的文檔可以看WWDC2016的PDF[2] :
What is Link-Time Optimization (LTO)?
Maximize runtime performance by optimizing at link-time
Inline functions across source files
Remove dead code
Enable powerful whole program optimizations
Google翻譯:
在鏈接時(shí)而非編譯時(shí)的優(yōu)化方式,可以增加程序運(yùn)行時(shí)的速度
優(yōu)化內(nèi)聯(lián)函數(shù)(個(gè)人認(rèn)為是文件間的函數(shù)做內(nèi)聯(lián)優(yōu)化)
移除沒(méi)有被調(diào)用的方法和代碼
整體優(yōu)化-讓你的程序變得更快
性能:
LTO Runtime Performance
Apple uses LTO extensively internally
Typically 10% faster than executables from regular Release builds
Multiplies with Profile Guided Optimization (PGO)
Reduces code size when optimizing for size
Google翻譯:
Apple已經(jīng)在自己的程序里大量使用
一般來(lái)說(shuō)比常規(guī)不帶LTO選項(xiàng)要快10%
可以與按配置優(yōu)化(PGO)疊加
可以用來(lái)減少代碼體積
這里值得注意的是,LTO選項(xiàng)需要配合編譯時(shí)選項(xiàng)來(lái)減少包體積。在Xcode的Optimization level中,如果使用-O3(讓代碼運(yùn)行更快但是體積變大),那么配合LTO可以實(shí)現(xiàn)運(yùn)行效率的提高,但是代碼體積會(huì)變大;如果使用-Os,那么LTO才會(huì)真的的優(yōu)化體積。
LTO已經(jīng)做了移除無(wú)用代碼的操作,即移除沒(méi)有被調(diào)用的selector,這樣一來(lái)我們就不用手動(dòng)去搜索并移除無(wú)用的方法了,這本身就是減少包體積的方法之一(待確認(rèn))。
從實(shí)踐情況來(lái)看,把開啟LTO的SDK變成.ipa來(lái)看,并沒(méi)有很大的體積變化,稍微減少了100k以內(nèi)。如果使用link-map來(lái)做統(tǒng)計(jì)的話,需要計(jì)算sdk-lto.thin,目前工具還不支持,所以沒(méi)有跑出來(lái)具體link-map的減少數(shù)據(jù),待之后補(bǔ)充。
相關(guān)鏈接