1 啟動(dòng)優(yōu)化
在iPhone的啟動(dòng)方式中铆惑,分為冷啟動(dòng)和熱啟動(dòng)兩種方式:
- 1、冷啟動(dòng)(Cold Launch):從零開始啟動(dòng)APP ,需要系統(tǒng)新創(chuàng)建一個(gè)進(jìn)程進(jìn)行啟動(dòng)驱负,這是一次完整的啟動(dòng)邑雅;
- 2片橡、熱啟動(dòng)(Hot Launch):APP已經(jīng)在內(nèi)存中,在后臺(tái)存活著淮野,再次點(diǎn)擊直接打開
我們一般說的啟動(dòng)優(yōu)化是指: 冷啟動(dòng)時(shí)的優(yōu)化捧书;
要達(dá)到優(yōu)化啟動(dòng)的目的,就需要知道在APP啟動(dòng)的時(shí)候骤星,有哪些流程经瓷,做了哪些事情;
APP的啟動(dòng)過程是從:點(diǎn)擊應(yīng)用icon圖標(biāo)洞难,到啟動(dòng)圖展示舆吮,再到首頁展示完成的過程:
打印查看啟動(dòng)時(shí)間:
通過添加環(huán)境變量可以打印出APP的啟動(dòng)時(shí)間分析(Edit scheme -> Run -> Arguments)
1、將DYLD_PRINT_STATISTICS設(shè)置為1
打印如下:
2、 如果需要更詳細(xì)的信息色冀,那就將DYLD_PRINT_STATISTICS_DETAILS設(shè)置為1
打印如下:
1.1 Main()函數(shù)執(zhí)行前
dyld(dynamic link editor):動(dòng)態(tài)鏈接器潭袱,用來裝載Mach-O文件(可執(zhí)行文件、動(dòng)態(tài)庫等)
-
dyld 加載可執(zhí)行文件mach-o文件到內(nèi)存中
- 裝載APP的可執(zhí)行文件锋恬,同時(shí)會(huì)遞歸加載所有依賴的動(dòng)態(tài)庫
- 當(dāng)dyld把可執(zhí)行文件屯换、動(dòng)態(tài)庫都裝載完畢后,會(huì)通知Runtime進(jìn)行下一步的處理
-
runtime加載類和分類:
- 調(diào)用map_images進(jìn)行可執(zhí)行文件內(nèi)容的解析和處理
- 在load_images中調(diào)用call_load_methods伶氢,調(diào)用所有Class和Category的+load方法
- 進(jìn)行各種objc結(jié)構(gòu)的初始化(注冊O(shè)bjc類 趟径、初始化類對(duì)象等等)
- 調(diào)用C++靜態(tài)初始化器和attribute((constructor))修飾的函數(shù)
所有初始化工作完成以后,dyld會(huì)調(diào)用main函數(shù)癣防,接下里就是UIApplicationMain函數(shù)的流程
1.1.2 啟動(dòng)優(yōu)化:
-
1蜗巧、dyld
- 減少動(dòng)態(tài)庫、合并一些動(dòng)態(tài)庫(定期清理不必要的動(dòng)態(tài)庫)
- 減少Objc類蕾盯、分類的數(shù)量幕屹、減少Selector數(shù)量(定期清理不必要的類、分類)
- 減少C++虛函數(shù)數(shù)量
- Swift盡量使用struct
-
2级遭、runtime
- 用+initialize方法和dispatch_once取代所有的
- attribute((constructor))望拖、C++靜態(tài)構(gòu)造器、ObjC的+load
-
3挫鸽、main
- 在不影響用戶體驗(yàn)的前提下说敏,盡可能將一些操作延遲冀瓦,不要全部都放在finishLaunching方法中
- 按需加載
2. 安裝包ipa瘦身
官方 App Thinning
App Thinning 是由蘋果公司推出的一項(xiàng)可以改善 App 下載進(jìn)程的新技術(shù)鲁僚,主要是為了解決用戶
下載 App 耗費(fèi)過高流量的問題,同時(shí)還可以節(jié)省用戶 iOS 設(shè)備的存儲(chǔ)空間构舟。
現(xiàn)在的 iOS 設(shè)備屏幕尺寸枫匾、分辨率越來越多樣化架诞,這樣也就需要更多資源來匹配不同的尺寸和分 辨率。 同時(shí)干茉,App 也會(huì)有 32 位谴忧、64 位不同芯片架構(gòu)的優(yōu)化版本。如果這些都在一個(gè)包里角虫,那 么用戶下載包的大小勢必就會(huì)變大沾谓。
App Thinning 會(huì)專門針對(duì)不同的設(shè)備來選擇只適用于當(dāng)前設(shè)備的內(nèi)容以供下載。比如:iPhone 6 只會(huì)下載 2x 分辨率的圖片資源上遥,iPhone 6plus 則只會(huì)下載 3x 分辨率的圖片資源搏屑。
2.1、使用Asset
- 使用Asset粉楚,將圖片區(qū)分,對(duì)應(yīng)的2X圖片和3X圖片,在上傳appStore以后會(huì)做不同的變體模软,減少下載包的大小
例如我現(xiàn)在的項(xiàng)目伟骨,由于是老項(xiàng)目,所有的圖片都是直接放在工程中的燃异,所以打包的時(shí)候沒有區(qū)分設(shè)備携狭,都會(huì)直接打包的app包中;
如果使用了現(xiàn)在的Asset回俐,將2x圖和3x圖區(qū)分開來逛腿,在appstore下載App的時(shí)候,會(huì)根據(jù)設(shè)備仅颇,只下載對(duì)應(yīng)的圖片单默,如果使用的是2x設(shè)備則只下載2x的圖片,3x的設(shè)備只下載3x的圖片忘瓦;
這樣就會(huì)減小從appstore下載時(shí)App包的大小搁廓。
2.2、刪除無用的圖片資源
項(xiàng)目中如果迭代過很多版本耕皮,圖片資源就會(huì)很多境蜕,需求在更新的同時(shí),所以可能會(huì)有很多無用的圖片凌停;
所以要使用一定的方法找到項(xiàng)目中不用的圖片粱年,并剔除掉;
- 通過 find 命令獲取 App 安裝包中的所有資源文件罚拟,比如 find /Users/daiming/Project/ - name台诗。
- 設(shè)置用到的資源的類型,比如 jpg舟舒、gif拉庶、png、webp秃励。
- 使用正則匹配在源碼中找出使用到的資源名氏仗,比如 pattern = @"@"(.+?)""。
- 使用 find 命令找到的所有資源文件夺鲜,再去掉代碼中使用到的資源文件皆尔,剩下的就是無用資源
了。 - 對(duì)于按照規(guī)則設(shè)置的資源名币励,我們需要在匹配使用資源的正則表達(dá)式里添加相應(yīng)的規(guī)則慷蠕,比如
@“image_%d”。 - 確認(rèn)無用資源后食呻,就可以對(duì)這些無用資源執(zhí)行刪除操作了流炕。這個(gè)刪除操作澎现,你可以使用
NSFileManger 系統(tǒng)類提供的功能來完成。
- 使用第三方軟件:LSUnusedResources 鏈接
下載完成以后直接運(yùn)行每辟,然后選擇工程所在的目錄剑辫,直接search,如果項(xiàng)目比較大的話渠欺,search的時(shí)間也會(huì)比較久妹蔽;
運(yùn)行以后,直接會(huì)顯示無用的圖片挠将,位置和大懈炱瘛:
這里選出來的圖片需要斟酌一下再去工程里面刪除,畢竟也是用正則表達(dá)式篩選出來的舔稀,有可能會(huì)有誤差乳丰,如果檢查過確實(shí)沒用,就可以直接刪除镶蹋。
2.3成艘、圖片資源壓縮
刪除了無用的圖片資源,有用的圖片資源其實(shí)也是可以優(yōu)化的贺归,那做法就是將圖片進(jìn)行壓縮和解壓處理:
對(duì)于 App 來說淆两,圖片資源總會(huì)在安裝包里占個(gè)大頭兒。對(duì)它們最好的處理拂酣,就是在不損失圖片 質(zhì)量的前提下盡可能地作壓縮秋冰。目前比較好的壓縮方案是,將圖片轉(zhuǎn)成 WebP婶熬。WebP 是 Google 公司的一個(gè)開源項(xiàng)目剑勾。
- 將圖片轉(zhuǎn)化成WebP,由于將圖片轉(zhuǎn)化成WebP和解壓的過程消耗較大赵颅,所以可以將圖片大于100k的進(jìn)行轉(zhuǎn)化虽另,其他的小圖片不做處理
2.4、刪除無用代碼
App 的安裝包主要是由資源和可執(zhí)行文件組成的饺谬,所以我們在掌握了對(duì)圖片資源的處理方式后捂刺, 需要再一起來看看對(duì)可執(zhí)行文件的瘦身方法。
可執(zhí)行文件就是 Mach-O 文件募寨,其大小是由代碼量決定的族展。通常情況下,對(duì)可執(zhí)行文件進(jìn)行瘦 身拔鹰,就是找到并刪除無用代碼的過程仪缸。而查找無用代碼時(shí),我們可以按照找無用圖片的思路列肢, 即:
- 找出方法和類的全集;
- 找到使用過的方法和類;
- 接下來恰画,取二者的差集得到無用代碼;
- 最后宾茂,由人工確認(rèn)無用代碼可刪除后,進(jìn)行刪除即可锣尉。
2.4.1刻炒、使用Link Map 統(tǒng)計(jì)所有的方法和類
在build settings中搜索link map决采,然后設(shè)為YES自沧;
設(shè)置build的輸出路徑,指定一個(gè)文件夾树瞭,然后指定輸出文件的格式和名字拇厢,一般是txt格式,設(shè)置好路徑后晒喷,直接運(yùn)行孝偎,就會(huì)在指定的文件夾下生成一個(gè).txt文件;
打開txt文件凉敲,以.o結(jié)尾的衣盾,都是生成的目標(biāo)文件,如圖:
測試demo我創(chuàng)建了兩個(gè)類爷抓,一個(gè)YYPerson势决,一個(gè)YYStudent;
LinkMap 文件分為三部分:Object File蓝撇、Section 和 Symbols果复。如下圖所示:
- Object File 包含了代碼工程的所有文件;
- Section 描述了代碼段在生成的 Mach-O 里的偏移位置和大小;
- Symbols 會(huì)列出每個(gè)方法、類渤昌、 block虽抄,以及它們的大小。
通過 LinkMap 独柑,你不光可以統(tǒng)計(jì)出所有的方法和類迈窟,還能夠清晰地看到代碼所占包大小的具體 分布,進(jìn)而有針對(duì)性地進(jìn)行代碼優(yōu)化忌栅。
如果項(xiàng)目較為復(fù)雜车酣,分析起來可能會(huì)很困難;
可借助第三方工具解析LinkMap文件:鏈接
運(yùn)行以后直接打開txt文件:
這個(gè)軟件能夠清晰的看到有哪些類狂秘,以及每個(gè)類的大泻Ь丁;
2.4.2者春、使用 MachOView 統(tǒng)計(jì)所有使用過的類
在products中找到.app包破衔,在finder中顯示,然后右擊顯示包內(nèi)容钱烟,找到可執(zhí)行文件:
然后使用 MachOView打開可執(zhí)行文件:
如圖上所示晰筛,我們可以看到 objc__selrefs 和 objc__classrefs 以及objc__superrefs 這三個(gè) section嫡丙。
其實(shí)這3個(gè)里面都是通過消息機(jī)制,objc__msgSend()函數(shù)調(diào)用過的對(duì)象方法读第,類方法曙博,類,元類等怜瞒;
但是父泳,這種查看方法并不是完美的,還會(huì)有些問題吴汪。原因在于惠窄, Objective-C 是門動(dòng)態(tài)語言,方法調(diào)用可以寫成在運(yùn)行時(shí)動(dòng)態(tài)調(diào)用漾橙,這樣就無法收集全所有調(diào)用的方法和類杆融。所以,我們通過這 種方法找出的無用方法和類就只能作為參考霜运,還需要二次確認(rèn)脾歇。
2.5 編譯器優(yōu)化
Strip Linked Product、Make Strings Read-Only淘捡、Symbols Hidden by Default設(shè)置為YES
去掉異常支持藕各,Enable C++ Exceptions、Enable Objective-C Exceptions設(shè)置為NO案淋, Other C Flags添加-fno-exceptions
利用AppCode檢測未使用的代碼:菜單欄 -> Code -> Inspect Code
其實(shí)啟動(dòng)優(yōu)化和ipa瘦身座韵,在于平時(shí)的很多細(xì)節(jié),比如如果是不用的圖片踢京,要立即刪除誉碴,不用的類和方法,也要及時(shí)清理瓣距,我們一般不刪除的原因是怕以后還有可能用到黔帕,但是一般都有版本控制,刪除了以后再要用可以從之前的版本中去找蹈丸;