iOS App 瘦身方案

縮減iOS安裝包大小是不少中大型APP都要作的事,通常首先會對資源文件下手,壓縮圖片/音頻,去除沒必要要的資源。這些資源優化作完後,咱們還能夠嘗試對可執行文件進行瘦身,項目越大,可執行文件佔用的體積越大,又由於AppStore會對可執行文件加密,致使可執行文件的壓縮率低,壓縮後可執行文件佔整個APP安裝包的體積比例大約有80%~90%,仍是挺值得優化的。下面介紹一下在研究可執行文件過程當中發現的能夠優化的點。研究的過程使用了linkmap,linkmap的介紹跟生成能夠參考另外一篇文章—iOS可執行文件的組成node

編譯選項

1.編譯器優化級別git

Build Settings->Optimization Level有幾個編譯優化選項,release版應該選擇Fastest, Smalllest,這個選項會開啓那些不增長代碼大小的所有優化,並讓可執行文件儘量小。github

2.去除符號信息安全

Strip Debug Symbols During Copy 和 Symbols Hidden by Default 在release版本應該設爲yes,能夠去除沒必要要的調試符號。Symbols Hidden by Default會把全部符號都定義成」private extern」,具體意思和做用我還不清楚,有待研究,但設了後會減少體積。這些選項目前都是XCode默認選項,但舊版XCode生成的項目可能不是,能夠檢查一下。app

其餘優化還能夠參考蘋果的官方文檔—CodeFootprint.pdf優化

第三方庫統計

項目裏會引入不少第三方靜態庫,若是能知道這些第三方庫在可執行文件裏佔用的大小,就能夠評估是否值得去找替代方案去掉這個第三方庫。咱們能夠從linkmap中統計出這個信息,我寫了個node.js腳本,能夠經過linkmap統計每一個.o目標文件佔用的體積和每一個.a靜態庫佔用的體積,並進行排序。詳見這裏(需FQ)。ui

ARC->MRC

有人提出用ARC寫的代碼編譯出來的可執行文件是會比用MRC大的,緣由大體是ARC代碼會在某些狀況多出一些retain和release的指令,例如調用一個方法,它返回的對象會被retain,退出做用域後會被release,MRC就不須要,彙編指令變多,機器碼變多,可執行文件就變大了。還有其餘細節實現的區別,先不糾結了。加密

那用ARC究竟會增大多少體積?我以爲從彙編指令的增多減小去算是很難算準確的,這東西涉及細節太多,仍是得從統計的角度計算。作了幾個對比試驗,統計了幾個同時支持ARC/MRC的開源項目在開啓/關閉ARC的狀況下__TEXT代碼段的大小對比。只對比__TEXT代碼段是由於:.net

ARC對可執行文件大小的影響幾乎都是在代碼段調試

可執行文件會進行某種對齊,例若有些段在不足32K的時候填充0直到對齊32K,若用可執行文件大小對比結果多是對齊後的,不許確。

實驗數據:

360桌面截圖20150202094249.jpg

結果是ARC大概會使代碼段增長10%的size,考慮代碼段佔可執行文件大約有80%,估計對整個可執行文件的影響會是8%。

能夠評估一下8%的體積降低是否是值得把項目裏某些模塊改爲MRC,這樣程序的維護成本上升了,通常不到特殊狀況不建議這麼作。

無用代碼

在項目裏新建一個類,給它添加幾個方法,但不要在任何地方import它,build完項目後觀察linkmap,你會發現這個類仍是被編譯進可執行文件了。

按C++的經驗,沒有被使用到的類和方法編譯器都會優化掉,不會編進最終的可執行文件,但object-c不同,由於object-c的動態特性,它能夠經過類和方法名反射得到這個類和方法進行調用,因此就算在代碼裏某個類沒被使用到,編譯器也無法保證這個類不會在運行時經過反射去調用,因此只要是在項目裏的文件,不管是否又被使用到都會被編譯進可執行文件。

對此咱們能夠經過腳本,遍歷整個項目的文件,找出全部沒有被引用的類文件和沒有被調用的方法,在保證沒有其餘地方動態調用的狀況下把它們去掉。若是整個項目歷時很長,歷時代碼遺留較多,這個清理對可執行文件省出的空間仍是挺可觀的。

類/方法名長度

觀察linkmap能夠發現每一個類和方法名都在__cstring段裏都存了相應的字符串值,因此類和方法名的長短也是對可執行文件大小是有影響的,緣由仍是object-c的動態特性,由於須要經過類/方法名反射找到這個類/方法進行調用,object-c對象模型會把類名,方法名列表都保存下來。

能夠考慮在編譯前把全部類和方法名進行混淆,把長名字替換成短名字,這樣作的好處除了縮小體積外,還對安全性有很大提高,別人拿到可執行文件對它class-dump出來的結果都是混淆後的類和方法名,就沒法從類和方法名中猜出某個方法是作什麼的,就難以掛鉤子進行hack。不過這樣有個缺點就是crash堆棧反解出來的堆棧方法名會是混淆後的,須要再加一層混淆->原名的轉換,實現和使用成本有點高。

實際上這部分佔用的長度比較小,中型項目也就幾百K,對安全性要求高的狀況能夠試試。

冗餘字符串

代碼上定義的全部靜態字符串都會記錄在在可執行文件的__cstring段,若是項目裏Log很是多,這個空間佔用也是可觀的,也有幾百K的大小,能夠考慮清理全部冗餘的字符串。另外若是有特別長的字符串,建議抽離保存成靜態文件,由於AppStore對可執行文件加密緻使壓縮率低,特別長的字符串抽離成靜態資源文件後壓縮率會比在可執行文件裏高不少。

CheckList

最後簡單把縮減iOS安裝包大小的各類方法列出來做爲CheckList:

安裝包大小優化.png

相關文章
相關標籤/搜索