袁宜霞
關(guān)鍵詞:軟件安裝包;可執(zhí)行文件;編譯優(yōu)化
0 引言
隨著移動應(yīng)用市場競爭越來越激烈,精細(xì)化運(yùn)營顯得越來越重要,手機(jī)軟件安裝包的大小不僅影響用戶下載意愿和用戶體驗(yàn),也會影響渠道分發(fā)和推廣成本甚至關(guān)系著研發(fā)維護(hù)成本,安裝包過大會帶來很多弊端。首先,用戶花費(fèi)流量來進(jìn)行下載意愿降低;包體的下載過程越長,用戶主動取消下載可能性越大,網(wǎng)絡(luò)不暢或者空間不足帶來的下載中斷概率增大;在手機(jī)空間不足導(dǎo)致用戶需要清理空間時,包體越大的軟件被清理的可能性越大。其次,在軟件分發(fā)渠道,有些廠商會限制用戶使用蜂窩網(wǎng)絡(luò)下載包體過大安裝包,或者大幅提高安裝包大的軟件分發(fā)費(fèi)用;買量推廣的成本增大而用戶轉(zhuǎn)換率降低。最后,安裝包越大意味著代碼和資源越多,研發(fā)團(tuán)隊需要更高的學(xué)習(xí)和維護(hù)成本,也更容易出錯。
本文以iOS安裝包為例,制定了一套安裝包縮減的整體方案并詳細(xì)闡述了原理與具體實(shí)現(xiàn)。
1 iOS 軟件安裝包分析
iOS軟件安裝包為IPA格式,此格式文件本質(zhì)是一種壓縮包,解壓縮后可以看到文件夾中含有一個Pay? load目錄。此目錄下包含了與IPA包同名的可執(zhí)行文件,資源文件、配置文件和lproj目錄。其中,可執(zhí)行文件是安裝包的核心部分,文件大小占據(jù)整個安裝包的較大比例,是逆向工程的重要目標(biāo)。資源文件主要包括圖片、視頻、音頻等,這類文件數(shù)量較多。lproj目錄包含各種本地化的字符串,為逆向工程提供重要線索[1]。
2 iOS 軟件安裝包縮減方案與實(shí)現(xiàn)
本文將從可執(zhí)行文件、資源優(yōu)化、產(chǎn)品功能優(yōu)化、編譯優(yōu)化和符號信息設(shè)置幾個方面來進(jìn)行安裝包縮減方案的制定與實(shí)現(xiàn)。
2.1 可執(zhí)行文件優(yōu)化與監(jiān)控方案
在iOS中可執(zhí)行文件的格式是Mach-O,LinkMap文件是集成開發(fā)工具Xcode生成可執(zhí)行文件時同步產(chǎn)生的鏈接信息,記錄了可執(zhí)行文件的各個組成部分,包括代碼段和數(shù)據(jù)段的分布情況。開發(fā)者需要在Xcode中打開Write Link Map File選項(xiàng)并編譯后才能獲得LinkMap文件。LinkMap文件有三個部分,分別是:Object files列舉了可執(zhí)行文件里所有.o文件,以及每個文件的編號;Sections是可執(zhí)行文件的段表,列舉了各個段在可執(zhí)行文件中的偏移位置和大小,包括代碼段和數(shù)據(jù)段;Symbols詳細(xì)存儲了每個文件中的各個字段位置和大小[2]。otool是Xcode自帶的Object file 展示工具,常用于逆向工程。
1) 刪除無用的類
由于iOS編程語言O(shè)bjective-C的動態(tài)特性,它使用類名和方法名對這個類和方法進(jìn)行調(diào)用,所以編譯器將項(xiàng)目中全部OC源文件編譯到可執(zhí)行文件,不論該類和方法是否被使用。在代碼中通過手動搜索al? loc、new、ClassName *等關(guān)鍵字代碼逐個排查所有類是否被使用的方法無疑是成本巨大且難以實(shí)施的。如下將詳細(xì)描述一個能自動化實(shí)現(xiàn)查找無用類的方案,通過下述方案獲得所有無用類的類名,并刪除這些無用類的代碼能帶來可執(zhí)行文件大小的縮減。
Xcode自帶的Analyze靜態(tài)分析工具能查找出一些沒有使用過的第三方庫,通過清除這類第三方庫實(shí)現(xiàn)壓縮安裝包的目的。開發(fā)時盡量減少第三方庫的引入,如果避免不了優(yōu)先選擇精簡庫,在LinkMap中可以看到第三方庫所占的包大小,可以作為是否引入該庫的評估依據(jù)。具體方法為:通過LinkMap中Ob? ject files 部分查看某個文件編號,再通過此編號在Symbols部分查看這個文件的每個段所占用大小并進(jìn)行累加,所得到的總大小就是該文件在可執(zhí)行文件中所占空間大小,此過程使用自動化腳本實(shí)現(xiàn)。例如:libWeChatSDK 這個靜態(tài)鏈接庫文件的文件編號為1260,把Sysmbols 中1260 對應(yīng)的所有段大小累加為0x00000040+0x00000040+0x000000A0=288B。
在不斷迭代開發(fā)中,工程中存在較大數(shù)量的重復(fù)代碼,這些代碼無用的能進(jìn)行刪除,有用的能通過函數(shù)化、面向?qū)ο缶幊痰确绞饺ミM(jìn)行優(yōu)化,從而減少安裝包大小。XCode中使用PMD靜態(tài)分析工具對代碼進(jìn)行掃描[3],在編譯項(xiàng)目后,會有匯總文檔給出重復(fù)代碼提示,且在項(xiàng)目代碼中也會明確提示當(dāng)前代碼與其他文件的多少行開始重復(fù)了。開發(fā)者依據(jù)提示可快捷地進(jìn)行重復(fù)代碼優(yōu)化或者刪除。
可執(zhí)行文件占據(jù)安裝包的大小比例高,所以在版本迭代開發(fā)中監(jiān)控可執(zhí)行文件增長很有必要。如3) 所述,利用自動化腳本對LinkMap文件進(jìn)行分析可以獲得每個代碼文件在可執(zhí)行文件中的大小,對比不同的兩個版本能夠獲得各代碼文件所占可執(zhí)行文件大小的變化,將這些變化進(jìn)行排序展示和監(jiān)控分析,對于控制可執(zhí)行文件的增長具有益處。表1為文件瘦身排行。
2.2 資源優(yōu)化
在iOS安裝包中主要包括圖片、音頻、視頻等,下面將從這幾個部分展開優(yōu)化。
1) 刪除未被使用的圖片、音頻和視頻資源
逐個使用資源名稱去整個工程項(xiàng)目代碼文件中搜索是否被引用的方法非常耗時,一個項(xiàng)目需要幾個小時,性價比極低,本文將介紹自動化實(shí)現(xiàn)查找未被使用圖片、音頻和視頻的方案,耗時僅僅幾分鐘甚至幾十秒。本方案的過程為:①獲得安裝包中的所有文件名,通過正則表達(dá)式r3"|w(.a+v|w?)m\.a[|sowggf||falpv|em|apc4c||rgmifv|jbp|ga|vjpi|emgp|bemg|pra|p|rnagm]|m"提ov|取wm出v|m所p有圖片、音頻和視頻資源名稱。eral s②trin在g:L(.i+n)k"M提a取p 文出件項(xiàng)目中代通碼過中正全則部表使達(dá)用式了r的".字* l符it?串。原因在于LinkMap文件中列舉出了工程代碼中所有的字符串,而資源文件一般都是使用字符串在代碼中被使用。如下LinkMap文件中Symbols部分的lit? eral string:后面跟隨的就是代碼中使用的字符串,pCnlogu,dqArlcboudme_對fou應(yīng)nd安對裝應(yīng)包安中裝的包圖片中資的源音C頻lou資dA源lbuqmr?. code_found.wav。
在不影響用戶體驗(yàn)的情況下,部分不常用的視頻、音頻和圖片資源、字體庫等可以放置到云端,用戶使用時實(shí)現(xiàn)按需下載,這在一定程度上能減少安裝包大小。利用XCode中的On-Demand Resources 配置,能便捷地將資源配置為按需加載,在需要使用時請求從AppStore中下載,這對于游戲或者包含大量多媒體資源的軟件安裝包縮減是非常有效的手段。
2.3 產(chǎn)品功能優(yōu)化
經(jīng)過長期累月迭代開發(fā)的軟件,軟件里面有大量的已經(jīng)失效功能或者曝光率低的功能代碼,這部分功能的刪減能帶來安裝包體大小的縮減。失效功能代碼的刪減相對比較容易實(shí)現(xiàn),但判定某個功能是否曝光率低是需要數(shù)據(jù)支撐并通過項(xiàng)目團(tuán)隊多方確認(rèn)。通常軟件界面需要較多圖片等資源,這里提出結(jié)合界面曝光率和界面二進(jìn)制文件大小兩個維度來確定是否刪減功能的方案。一方面,通過在View Controller 中加入曝光上報數(shù)據(jù),獲取客戶端界面曝光率;另一方面,通過2.1 中所述自動化方法從LinkMap 獲取View Controller二進(jìn)制文件的大小,從而估計這個模塊的大小。最后,對于提取出的曝光率低而二進(jìn)制文件占比又比較大的界面,在項(xiàng)目團(tuán)隊進(jìn)行討論,有重點(diǎn)地進(jìn)行功能優(yōu)化、刪減或者改為網(wǎng)頁形式實(shí)現(xiàn),例如生命周期不長的運(yùn)營活動類需求就比較適合使用網(wǎng)頁形式實(shí)現(xiàn)。
2.4 編譯優(yōu)化和符號信息設(shè)置
1) 編譯優(yōu)化
Xcode采用Clang編譯,Optimization Level中提供了6個編譯模式[5],分別是:不做代碼優(yōu)化的None,優(yōu)化代碼性能最小影響編譯時間的Fast,開啟不依賴時間/空間的所有優(yōu)化項(xiàng)的Faster,開啟全部優(yōu)化會導(dǎo)致可執(zhí)行文件增大的Fastest,開啟除增加包體大小以外的全部優(yōu)化項(xiàng)的Fastest Smallest,激進(jìn)不太推薦的Fastest, Aggressive Optimization。在安裝包的發(fā)布版本中,選擇Fastest Smallest編譯模式,在保證代碼執(zhí)行效率的同時最小限度影響包大小。
2) 符號信息設(shè)置
symbols是所有的變量、類、函數(shù)、枚舉、變量和地址映射關(guān)系,以及一些在調(diào)試的時候使用到的用于定位代碼在源碼位置的調(diào)試符號,和斷點(diǎn)定位以及堆棧符號化有很重要的關(guān)系。對于發(fā)布出去的版本而言,并不是所有的符號都是必要的,比如調(diào)試符號,所以這類型符號的刪減也能帶來包體大小的縮減。在Xcode 中將Strip Linked Product設(shè)置為yes能清除不必要的符號信息,同時把Deployment Postprocessing 設(shè)置為YES 使其生效。將Symbols Hidden by Default設(shè)置為yes把symbols申明為私有外部符號也能減少包大小。
3 結(jié)束語
隨著技術(shù)發(fā)展和用戶需求的增加,手機(jī)軟件安裝包越來越大,這提高了用戶下載成本,對用戶新增和軟件留存率有所影響,在進(jìn)行軟件推廣時也面臨成本增加、用戶轉(zhuǎn)化率低和各類限制,無形中也會增加軟件研發(fā)維護(hù)成本。針對iOS軟件安裝包,本文從多個方面制定了一套詳細(xì)的自動化縮減方案,并進(jìn)行自動化監(jiān)控,希望能協(xié)助移動應(yīng)用項(xiàng)目團(tuán)隊進(jìn)一步提升用戶體驗(yàn),打造精品。