Swift 項(xiàng)目編譯優(yōu)化(一)

前言
前段時(shí)間筆者組內(nèi)同事十分快速地開(kāi)發(fā)了一個(gè)應(yīng)用(不妨設(shè)應(yīng)用名為QiShareDemo)归敬,筆者在使用8+128的Mac Air 運(yùn)行項(xiàng)目的時(shí)候琉闪,發(fā)現(xiàn)項(xiàng)目編譯時(shí)間比較久和橙,查看了相關(guān)資料,并做了部分實(shí)踐芋酌,落地了這篇文章增显。
筆者在 clone 了 QiShareDemo 后,發(fā)現(xiàn)全量編譯編譯項(xiàng)目的編譯時(shí)間為105.207s脐帝;
后來(lái)經(jīng)過(guò)筆者的部分優(yōu)化編譯時(shí)間處理后同云,全量編譯項(xiàng)目的時(shí)間縮短為44.573s;
當(dāng)然這里還可以繼續(xù)做優(yōu)化堵腹,可以根據(jù)項(xiàng)目中具體的代碼的編譯耗時(shí)排序炸站,處理那些編譯耗時(shí)較長(zhǎng)的代碼。

一疚顷、名詞簡(jiǎn)介

下邊筆者對(duì)本文中提到的名詞做一個(gè)簡(jiǎn)單介紹旱易。

1. 全量編譯

以Xcode編譯過(guò)程為例,筆者理解的全量編譯的一種情況為:把Xcode 編譯項(xiàng)目時(shí)生成的Derived Data 刪除后腿堤,再次編譯項(xiàng)目的過(guò)程阀坏。

2. 增量編譯

以Xcode編譯過(guò)程為例,筆者理解的增量編譯的一種情況為:Xcode 已編譯過(guò)項(xiàng)目的情況下笆檀,我們又修改了部分文件忌堂,那么編譯的時(shí)候,就會(huì)編譯我們修改過(guò)的文件酗洒,及引用過(guò)相關(guān)文件的文件士修。

3. Swift Compiler

如果項(xiàng)目不是 Objective-C 和 Swift 混編的項(xiàng)目而是純 Swift 項(xiàng)目,那么編譯過(guò)程用的是 Swift Compiler樱衷,筆者在下文中第三部分的2.1.2部分有提到詳情棋嘲。關(guān)于編譯的更多詳情可以查看 淺談編譯過(guò)程

二、Swift 項(xiàng)目的編譯過(guò)程

使用 Xcode 查看項(xiàng)目具體編譯過(guò)程的方式如下:

1. 用 Xcode 查看項(xiàng)目具體編譯過(guò)程

用 Xcode 查看項(xiàng)目編譯過(guò)程方式:command + b 編譯項(xiàng)目矩桂,在 Xcode 中沸移,按下圖方式查看具體編譯過(guò)程。

compileProcess1

筆者根據(jù) Xcode 編譯項(xiàng)目過(guò)程,做了如下 Swift 項(xiàng)目編譯過(guò)程示意圖阔籽。

SwiftCompileProcess.png

2. 查看項(xiàng)目編譯時(shí)間

我們的目的是要優(yōu)化項(xiàng)目的編譯時(shí)間流妻,那么首先我們應(yīng)該知道當(dāng)前編譯時(shí)間。
查看項(xiàng)目編譯時(shí)間的方式為:在終端中輸入如下命令:defaults write com.apple.dt.Xcode ShowBuildOperationDuration YES
之后在 Xcode 頂部的 切換Scheme和運(yùn)行設(shè)備的那一欄中即可看到具體編譯時(shí)間笆制。
查看具體編譯時(shí)間方式如下圖所示:

Xcode compile Time

上圖是查看項(xiàng)目總體編譯時(shí)間的方式,那么我們想要對(duì)項(xiàng)目做編譯時(shí)間優(yōu)化涣达,就要找出來(lái)編譯耗時(shí)長(zhǎng)的部分在辆。
上文中提到了通過(guò) Xcode 查看項(xiàng)目具體編譯時(shí)間的方式,筆者也放了如下部分示意圖度苔。

compileProcess detail

三匆篓、減少項(xiàng)目編譯時(shí)間的考慮

1. 調(diào)整 Xcode 的Build Settings 中的配置

關(guān)于調(diào)整 Xcode 的 Build Settings 中的配置,筆者查詢資料后發(fā)現(xiàn)在 Xcode10 及之前調(diào)整空間比較大寇窑,在 Xcode11 的時(shí)候鸦概,筆者初步嘗試后,發(fā)現(xiàn)調(diào)整 Xcode 的 Build Settings 中的配置對(duì)于優(yōu)化項(xiàng)目編譯時(shí)間影響不大甩骏。

2. 把穩(wěn)定三方打包成 Framework

筆者在分析了項(xiàng)目編譯時(shí)間后窗市,發(fā)現(xiàn) QiShareDemo 中引入的每個(gè)三方都各自花費(fèi)了20s+的時(shí)間,記不清是查看了網(wǎng)上的文章示例還是如何饮笛,想到了如果在使用這些三方的過(guò)程中咨察,不會(huì)頻繁改動(dòng)這些三方源代碼的情況下,可以把這些三方打包成 Framework福青,嘗試解決編譯耗時(shí)久的問(wèn)題摄狱。
經(jīng)過(guò)嘗試把項(xiàng)目中的三方打成 Framework,供 QiShareDemo 使用后无午,就得到了一個(gè)明顯的減少編譯耗時(shí)的成效媒役。
從開(kāi)始的筆者在 clone 了 QiShareDemo 后,全量編譯編譯項(xiàng)目的編譯時(shí)間為105.207s宪迟;
后來(lái)經(jīng)過(guò)筆者初步把三方打包成 Framework 后酣衷,全量編譯項(xiàng)目的時(shí)間縮短為44.573s;

2.1 淺談編譯耗時(shí)縮短的原因
2.1.1 把穩(wěn)定三方打成 Framework 對(duì)編譯影響

可以結(jié)合上一篇文章淺談編譯過(guò)程來(lái)談這個(gè)問(wèn)題踩验。
關(guān)于項(xiàng)目直接使用 Framework 鸥诽,會(huì)減少編譯時(shí)間的原因,組內(nèi)同學(xué) 沐靈洛奇舞647 都提及過(guò)箕憾,筆者推測(cè)原因是:
從編譯過(guò)程來(lái)看牡借,項(xiàng)目直接使用 Framework 相比使用 Cocoapods 的源代碼依賴,就省了預(yù)編譯袭异、詞法分析钠龙、語(yǔ)法分析、生成中間代碼、生成目標(biāo)文件的過(guò)程碴里。所以就減少了編譯時(shí)間沈矿。(編譯過(guò)程更多信息可查看 淺談編譯過(guò)程)
這部分還有一個(gè)劣勢(shì),組內(nèi)同學(xué) 大成小棧 提到說(shuō)咬腋,打成Framework 后在調(diào)試修改源代碼的時(shí)候就不方便了羹膳。這個(gè)是必然的,所以最好是把那些穩(wěn)定的三方打包成 Framework 根竿,或者是和組內(nèi)同學(xué)分工合作陵像,分別負(fù)責(zé)某個(gè)三方。

2.1.2 Objective-C 和 Swift 混編耗時(shí)影響

組內(nèi)同學(xué) 沐靈洛 還結(jié)合著筆者發(fā)出的編譯過(guò)程圖寇壳,提及過(guò)Swift 和 OC 項(xiàng)目混編相對(duì)于純 Swift 項(xiàng)目可能耗時(shí)更多的問(wèn)題醒颖。
這部分筆者的推測(cè)是看 Swift 項(xiàng)目的編譯過(guò)程。如果只是單純的 Swift 項(xiàng)目壳炎,編譯的前端過(guò)程用 Swift 編譯器就夠用了泞歉。
如果是Swift 和 OC 混編的項(xiàng)目,編譯的前端過(guò)程還會(huì)用到 Clang 匿辩,Clang 會(huì)把 C腰耙、Objective-C 的 API 向Swift API 做一個(gè)對(duì)應(yīng)。我想這個(gè)過(guò)程多少會(huì)比 Swift 編譯器單純編譯Swift 代碼多一些編譯耗時(shí)的增加撒汉。
下邊筆者放了一個(gè)Swift Compiler 架構(gòu)圖沟优,筆者是以流程圖的方式繪制制作的Swift Compiler 架構(gòu)圖。

SwiftCompilerArchitecture.png

注:在之前的文章 淺談編譯過(guò)程中筆者介紹了 GCC睬辐、LLVM編譯器挠阁,Swift 語(yǔ)言的編譯器是用的自有的Swift Compiler。

3. 使用工具查看項(xiàng)目中代碼編譯耗時(shí)

可以使用工具 BuildTimeAnalyzer-for-Xcode 查看項(xiàng)目中自己寫(xiě)的代碼的編譯時(shí)間溯饵。
筆者使用 BuildTimeAnalyzer-for-Xcode 查看了項(xiàng)目編譯時(shí)間侵俗,找出了2處編譯時(shí)間耗時(shí)的地方。
下圖是筆者使用 BuildTimeAnalyzer-for-Xcode 查看出的項(xiàng)目編譯時(shí)間耗時(shí)情況丰刊。
筆者在Target -> Build Settings -> Swift Compiler 的 Other Swift Flags 中添加了如下配置:

-Xfrontend -warn-long-function-bodies=100
-Xfrontend -warn-long-expression-type-checking=100
-Xfrontend -debug-time-function-bodies

上述配置內(nèi)容用于添加使用 BuildTimeAnalyzer-for-Xcode 的配置隘谣,用于查看出方法或表達(dá)式編譯耗時(shí)超過(guò)100ms的位置以警告的形式表現(xiàn)出來(lái)。

下邊筆者舉2個(gè)遇到的編譯耗時(shí)的代碼示例啄巧。

3.1 ??(nil-coalescing 空合并運(yùn)算符) 及 ”+“拼接在一起的耗時(shí)

這種 “??” 和 “+”拼接字符串用在一起時(shí)寻歧,在編譯過(guò)程中會(huì)比較耗時(shí)。最好改成短短的小代碼語(yǔ)句秩仆。

compileTime1

經(jīng)過(guò)筆者把上述耗時(shí)代碼使用 if let 的方式處理后码泛,編譯耗時(shí)的問(wèn)題已得到了解決。

compileTime2
3.2 使用 snapkit 時(shí)候可能遇到的編譯耗時(shí)

筆者打開(kāi)了測(cè)出的使用 Snapkit 的過(guò)程中澄耍,可能遇到的編譯耗時(shí)的代碼噪珊。檢測(cè)編譯耗時(shí)的示意圖如下:

compileTime3

如果把上述的紅色箭頭指向的代碼改成使用藍(lán)色箭頭指向的代碼可以解決編譯耗時(shí)的問(wèn)題晌缘。
筆者收獲是:使用Snapkit 布局的時(shí)候,參考值盡可能是一個(gè)明確值痢站,盡可能不要設(shè)置參考的時(shí)候磷箕,再讓編譯器去幫我們計(jì)算值,我們可以盡可能多的告訴編譯器我們知道的事情阵难。

四岳枷、其他考慮方向

1. SwiftUI

使用SwiftUI可以實(shí)時(shí)查看代碼顯示效果,并可以在不同設(shè)備上預(yù)覽效果呜叫。
使用 SwiftUI 可以提高開(kāi)發(fā)效率嫩舟。
SwiftUI 官方教程:Learn to Make Apps with SwiftUI

2. Swift的HotReload嘗試

考慮到市面上 Flutter 支持 HotReload 可以極大提升開(kāi)發(fā)效率,其實(shí)Swift 也支持 Hot Reload 怀偷,目前筆者只試過(guò) injectionIII Demo 的HotReload,目前不做過(guò)多介紹播玖。
Swift 的 HotReload 嘗試可以使用工具 Injection III 椎工。
如下網(wǎng)址中有 InjectionIII 的使用介紹及使用Demo。injectionIII
Injection III App Store下載地址:https://apps.apple.com/cn/app/injectioniii/id1380446739?mt=12

五蜀踏、參考學(xué)習(xí)網(wǎng)址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市果覆,隨后出現(xiàn)的幾起案子颅痊,更是在濱河造成了極大的恐慌,老刑警劉巖局待,帶你破解...
    沈念sama閱讀 222,729評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件斑响,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡钳榨,警方通過(guò)查閱死者的電腦和手機(jī)舰罚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)薛耻,“玉大人营罢,你說(shuō)我怎么就攤上這事”荩” “怎么了饲漾?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,461評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)缕溉。 經(jīng)常有香客問(wèn)我考传,道長(zhǎng),這世上最難降的妖魔是什么倒淫? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,135評(píng)論 1 300
  • 正文 為了忘掉前任伙菊,我火速辦了婚禮败玉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘镜硕。我一直安慰自己运翼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布兴枯。 她就那樣靜靜地躺著血淌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪财剖。 梳的紋絲不亂的頭發(fā)上悠夯,一...
    開(kāi)封第一講書(shū)人閱讀 52,736評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音躺坟,去河邊找鬼沦补。 笑死,一個(gè)胖子當(dāng)著我的面吹牛咪橙,可吹牛的內(nèi)容都是我干的夕膀。 我是一名探鬼主播,決...
    沈念sama閱讀 41,179評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼美侦,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼产舞!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起菠剩,我...
    開(kāi)封第一講書(shū)人閱讀 40,124評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤易猫,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后具壮,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體准颓,經(jīng)...
    沈念sama閱讀 46,657評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評(píng)論 3 342
  • 正文 我和宋清朗相戀三年嘴办,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了瞬场。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,872評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡涧郊,死狀恐怖贯被,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情妆艘,我是刑警寧澤彤灶,帶...
    沈念sama閱讀 36,533評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站批旺,受9級(jí)特大地震影響幌陕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜汽煮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評(píng)論 3 336
  • 文/蒙蒙 一搏熄、第九天 我趴在偏房一處隱蔽的房頂上張望棚唆。 院中可真熱鬧,春花似錦心例、人聲如沸宵凌。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,700評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)瞎惫。三九已至,卻和暖如春译株,著一層夾襖步出監(jiān)牢的瞬間瓜喇,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,819評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工歉糜, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留乘寒,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,304評(píng)論 3 379
  • 正文 我出身青樓匪补,卻偏偏與公主長(zhǎng)得像肃续,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子叉袍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評(píng)論 2 361