符號表優(yōu)化
盡可能的隱藏符號表:
如果我們寫了10個方法豪墅,但是并不是全都讓外部來調(diào)用,就需要把這部分符號隱藏
//暴露符號表 __attribute__((visibility("default")))
//隱藏符號
//不會放到Dynamic Symbol Table 里斩萌,所以不會被dyld找到 __attribute__((visibility("hidden")))
參考一下fishhook的圖:
由上圖可見:_la_symbol ptr 會指向 indirect symbol table , indirect symbol table(只存儲了symbol table的索引) 指向symbol table术裸,symbol table(包含string table的指針 和 type袭艺、desc等) 指向了string table猾编。
那么我們最終優(yōu)化的就是 _la_symbol ptr 升敲,也就是說我們設(shè)置 了
__attribute__((visibility("hidden")))
,符號表就不會被加載到 _la_symbol里瘪撇,進(jìn)而減少符號的體積
xcode提供了一個全局的開關(guān)倔既,用來設(shè)置符號的默認(rèn)可見性:
我們可以設(shè)置為NO,隱藏符號表,然后對需要暴露的方法設(shè)置:
__attribute__((visibility("default")))
動態(tài)庫和靜態(tài)庫的選擇
在靜態(tài)鏈接(ld)階段佩谣,動態(tài)庫會把整個lib復(fù)制進(jìn)mach-o中茸俭,這顯然不太符合包體積優(yōu)化的需求安皱。
但是靜態(tài)庫在靜態(tài)鏈接階段,僅把用到的文件link到mach-o中腾窝,這一點(diǎn)和動態(tài)庫區(qū)別很大腺晾,符合包體積優(yōu)化需求。
對于靜態(tài)庫归形,盡量不要使用-Objc (加載所有object c文件)或 all_load(加載所有文件)暇榴,顯然這不太合適,可用-force_load替代蕉世。
另外,不選用動態(tài)庫的另外一個原因是:動態(tài)庫單獨(dú)享有一份__TEXT段奸例,而靜態(tài)庫也享有一份_TEXT段向楼。
如果動態(tài)庫、靜態(tài)庫有些類逻卖、方法都是相同的昭抒,會在靜態(tài)庫炼杖、動態(tài)庫各有一份__TEXT段盗迟,造成不必要的冗余。
下面我寫了個動態(tài)庫:(dylib有單獨(dú)__TEXT罩扇,所以不會和靜態(tài)庫的__TEXT產(chǎn)生符號沖突)
關(guān)于xcode配置的一些選項(xiàng)
1怕磨、(Levels選項(xiàng)內(nèi))Generate Debug Symbols 設(shè)置為NO肠鲫,這個配置選項(xiàng)應(yīng)該會讓你減去小半的體積或粮。注意這個如果設(shè)置成NO就不會在斷點(diǎn)處停下氯材,
這個選項(xiàng)不會生成DSYM文件,但是不建議這么做袋毙,因?yàn)镈SYM文件是解析crash的重要途徑冗尤,如:bugly就需要上傳DSYM文件。
2皆看、Strip Linked Product:If enabled, the linked product of the build will be stripped(剪裁背零、拖掉)of symbols when performing deployment postprocessing.
當(dāng)設(shè)置成YES , 會剪裁掉不需要的符號徙瓶,但前提是把Deployment Postprocessing 設(shè)置為 YES 。
3禾乘、Strip Style:
- All Symbols - 完全剪裁符號虽缕,剪裁效果:強(qiáng)
- Non-Global Symbols - 剪裁掉非全局符號(global symbols供外部符號鏈接時候使用)蒲稳,剪裁效果:中
- Debugging Symbols - 剪裁掉 debugging 的符號江耀,發(fā)布app之后可以選擇此項(xiàng)诉植,剪裁效果:弱
注:靜態(tài)庫不要選 All Symbols,因?yàn)閘d在進(jìn)行l(wèi)ink的時候會用到符號來進(jìn)行鏈接舌稀。
4壁查、Debug Information Level:當(dāng)設(shè)置成Line tables only , 就只會生成方法名剔应,行號等,但不會包含變量席怪、方法參數(shù)等上下文
設(shè)置后可以看到包體積的確有少量縮減挂捻;
5细层、Dead Code Stripping ,刪除 dead code 符號疫赎,項(xiàng)目中無用文件較多時碎节,可以減少體積狮荔。
6、Debug Information Format 晚树,debug模式下設(shè)置為DWARF即可雅采,release模式下設(shè)置為DWARF with dSYM File即可
解釋一下DWARF:每個文件被編譯成.o 后綴的中間文件,這個文件會包含調(diào)試信息宝鼓,也就是DWARF (debugging with attributed record formats)
補(bǔ)充一點(diǎn):我們即使生成了dsym文件,發(fā)布到 appstore 之后蛉签,ipa 也不會包含這個dsym文件沥寥,這個文件只給開發(fā)者來解析crash日志使用。
下面我們用file命令查看dsym乒验、dwarf文件格式:
% file test.app.dSYM
test.app.dSYM: directory //dsym實(shí)際是個文件夾
//我們繼續(xù)查看 dsym 文件夾里面內(nèi)容蒂阱,有一個test文件狂塘,他就是dwarf格式的文件
% file test
test: Mach-O 64-bit dSYM companion file arm64 //可以看到這個dwarf文件是一個mach-o文件 荞胡,并且是64位的,支持 arm64架構(gòu)
再看一下這個dsym文件的格式——沒有了__TEXT 和 __DATA段廊营,而多了__DWARF段:
7萝勤、編譯器優(yōu)化級別
Build Settings->Optimization Level有幾個編譯優(yōu)化選項(xiàng),release版應(yīng)該選擇Fastest, Smalllest[-Os]慎式,這個選項(xiàng)會開啟那些不增加代碼大小的全部優(yōu)化趟径,并讓可執(zhí)行文件盡可能小。
arm 架構(gòu)優(yōu)化
舍棄架構(gòu) armv7掌眠、armv7s蓝丙、i386、x86迅腔,保留arm64即可,因?yàn)閺?s往后都是arm64的
- armv7 用于支持4s和4掠兄,4s是2011年11月正式上線蚂夕,雖然還有小部分人在使用腋逆,但是追求包體大小的完全可以舍棄了。
- armv7s 用于iPhone5等脂,基本也可以刪除了
- i386 是模擬器架構(gòu)撑蚌,也可以刪除
- x86 是mac架構(gòu)争涌,可以刪除
檢測各個模塊占用大小
要想知道優(yōu)化哪些庫,那么我們要先生成link map模软,然后對每個庫進(jìn)行分析
xcode要開啟Write Link Map File饮潦,然后指定路徑即可
https://github.com/zgzczzw/LinkMapParser(解析格式)
下面是解析完的情況:我們可以針對某些特大的包進(jìn)行符號表剪裁害晦、資源壓縮、arm架構(gòu)剪裁等
================================================================================
linkmap.txt各模塊體積匯總
================================================================================
Creating Result File : BaseLinkMapResult.txt
libavcodec.a 15.09M
WeexSDK 4.95M
opencv2 3.64M
React 3.04M
libavformat.a 1.49M
SwiftProtobuf 1.24M
libmp4v2.a 1.23M
libx264.a 1.18M
libPaymentControl.a 1.17M
libavfilter.a 1.14M
linker synthesized 1.12M
Samyou 1.04M
總體積: 179.32M
================================================================================
圖片處理
用 LSUnusedResource 這個軟件查找項(xiàng)目中沒有用到的圖片鲫剿,然后刪除
https://github.com/tinymind/LSUnusedResources/raw/master/Release/LSUnusedResources.app.zip
用 ImageOptim 壓縮圖片的大小灵莲,如果是png圖片殴俱,可以針對不需要透明的圖片剪裁掉他的alpha通道枚抵。 ImageOptim是支持這一項(xiàng)的
對于PNG圖片來說汽摹,文件可能更大苦锨,但是解碼會相對較快,而Xcode會把 PNG圖片進(jìn)行解碼優(yōu)化之后引入工程拉庶。
對于JPEG圖片來說氏仗,他體積更小夺鲜,但是解碼要消耗更長的時間,因?yàn)镴PEG解壓算法比基于zip的PNG算法更加復(fù)雜床佳。
查找冗余的文件
Fui : https://github.com/dblock/fui
注意這里:有些用不到的文件,其中包含+load方法杆麸,這種應(yīng)該注意昔头,因?yàn)橹灰募⑴c編譯,+load方法就會被調(diào)用莱革,不要輕易刪除