Swift 項目編譯優化(一)


前言
前段時間筆者組內同事十分快速地開發了一個應用(不妨設應用名為QiShareDemo),筆者在使用8+128的Mac Air 運行項目的時候,發現項目編譯時間比較久,查看了相關資料,並做了部分實踐,落地了這篇文章。
筆者在 clone 了 QiShareDemo 后,發現全量編譯編譯項目的編譯時間為105.207s;
后來經過筆者的部分優化編譯時間處理后,全量編譯項目的時間縮短為44.573s;
當然這里還可以繼續做優化,可以根據項目中具體的代碼的編譯耗時排序,處理那些編譯耗時較長的代碼。

一、名詞簡介

下邊筆者對本文中提到的名詞做一個簡單介紹。

1. 全量編譯

以Xcode編譯過程為例,筆者理解的全量編譯的一種情況為:把Xcode 編譯項目時生成的Derived Data 刪除后,再次編譯項目的過程。

2. 增量編譯

以Xcode編譯過程為例,筆者理解的增量編譯的一種情況為:Xcode 已編譯過項目的情況下,我們又修改了部分文件,那么編譯的時候,就會編譯我們修改過的文件,及引用過相關文件的文件。

3. Swift Compiler

如果項目不是 Objective-C 和 Swift 混編的項目而是純 Swift 項目,那么編譯過程用的是 Swift Compiler,筆者在下文中第三部分的2.1.2部分有提到詳情。關於編譯的更多詳情可以查看 淺談編譯過程

二、Swift 項目的編譯過程

使用 Xcode 查看項目具體編譯過程的方式如下:

1. 用 Xcode 查看項目具體編譯過程

用 Xcode 查看項目編譯過程方式:command + b 編譯項目,在 Xcode 中,按下圖方式查看具體編譯過程。

compileProcess1

筆者根據 Xcode 編譯項目過程,做了如下 Swift 項目編譯過程示意圖。

SwiftCompileProcess.png

2. 查看項目編譯時間

我們的目的是要優化項目的編譯時間,那么首先我們應該知道當前編譯時間。
查看項目編譯時間的方式為:在終端中輸入如下命令:defaults write com.apple.dt.Xcode ShowBuildOperationDuration YES
之后在 Xcode 頂部的 切換Scheme和運行設備的那一欄中即可看到具體編譯時間。
查看具體編譯時間方式如下圖所示:

Xcode compile Time

上圖是查看項目總體編譯時間的方式,那么我們想要對項目做編譯時間優化,就要找出來編譯耗時長的部分。
上文中提到了通過 Xcode 查看項目具體編譯時間的方式,筆者也放了如下部分示意圖。

compileProcess detail

三、減少項目編譯時間的考慮

1. 調整 Xcode 的Build Settings 中的配置

關於調整 Xcode 的 Build Settings 中的配置,筆者查詢資料后發現在 Xcode10 及之前調整空間比較大,在 Xcode11 的時候,筆者初步嘗試后,發現調整 Xcode 的 Build Settings 中的配置對於優化項目編譯時間影響不大。

2. 把穩定三方打包成 Framework

筆者在分析了項目編譯時間后,發現 QiShareDemo 中引入的每個三方都各自花費了20s+的時間,記不清是查看了網上的文章示例還是如何,想到了如果在使用這些三方的過程中,不會頻繁改動這些三方源代碼的情況下,可以把這些三方打包成 Framework,嘗試解決編譯耗時久的問題。
經過嘗試把項目中的三方打成 Framework,供 QiShareDemo 使用后,就得到了一個明顯的減少編譯耗時的成效。
從開始的筆者在 clone 了 QiShareDemo 后,全量編譯編譯項目的編譯時間為105.207s;
后來經過筆者初步把三方打包成 Framework 后,全量編譯項目的時間縮短為44.573s;

2.1 淺談編譯耗時縮短的原因
2.1.1 把穩定三方打成 Framework 對編譯影響

可以結合上一篇文章淺談編譯過程來談這個問題。
關於項目直接使用 Framework ,會減少編譯時間的原因,組內同學 沐靈洛奇舞647 都提及過,筆者推測原因是:
從編譯過程來看,項目直接使用 Framework 相比使用 Cocoapods 的源代碼依賴,就省了預編譯、詞法分析、語法分析、生成中間代碼、生成目標文件的過程。所以就減少了編譯時間。(編譯過程更多信息可查看 淺談編譯過程)
這部分還有一個劣勢,組內同學 大成小棧 提到說,打成Framework 后在調試修改源代碼的時候就不方便了。這個是必然的,所以最好是把那些穩定的三方打包成 Framework ,或者是和組內同學分工合作,分別負責某個三方。

2.1.2 Objective-C 和 Swift 混編耗時影響

組內同學 沐靈洛 還結合着筆者發出的編譯過程圖,提及過Swift 和 OC 項目混編相對於純 Swift 項目可能耗時更多的問題。
這部分筆者的推測是看 Swift 項目的編譯過程。如果只是單純的 Swift 項目,編譯的前端過程用 Swift 編譯器就夠用了。
如果是Swift 和 OC 混編的項目,編譯的前端過程還會用到 Clang ,Clang 會把 C、Objective-C 的 API 向Swift API 做一個對應。我想這個過程多少會比 Swift 編譯器單純編譯Swift 代碼多一些編譯耗時的增加。
下邊筆者放了一個Swift Compiler 架構圖,筆者是以流程圖的方式繪制制作的Swift Compiler 架構圖。

SwiftCompilerArchitecture.png

注:在之前的文章 淺談編譯過程中筆者介紹了 GCC、LLVM編譯器,Swift 語言的編譯器是用的自有的Swift Compiler。

3. 使用工具查看項目中代碼編譯耗時

可以使用工具 BuildTimeAnalyzer-for-Xcode 查看項目中自己寫的代碼的編譯時間。
筆者使用 BuildTimeAnalyzer-for-Xcode 查看了項目編譯時間,找出了2處編譯時間耗時的地方。
下圖是筆者使用 BuildTimeAnalyzer-for-Xcode 查看出的項目編譯時間耗時情況。
筆者在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

上述配置內容用於添加使用 BuildTimeAnalyzer-for-Xcode 的配置,用於查看出方法或表達式編譯耗時超過100ms的位置以警告的形式表現出來。

下邊筆者舉2個遇到的編譯耗時的代碼示例。

3.1 ??(nil-coalescing 空合並運算符) 及 ”+“拼接在一起的耗時

這種 “??” 和 “+”拼接字符串用在一起時,在編譯過程中會比較耗時。最好改成短短的小代碼語句。

compileTime1

經過筆者把上述耗時代碼使用 if let 的方式處理后,編譯耗時的問題已得到了解決。

compileTime2

3.2 使用 snapkit 時候可能遇到的編譯耗時

筆者打開了測出的使用 Snapkit 的過程中,可能遇到的編譯耗時的代碼。檢測編譯耗時的示意圖如下:

compileTime3

如果把上述的紅色箭頭指向的代碼改成使用藍色箭頭指向的代碼可以解決編譯耗時的問題。
筆者收獲是:使用Snapkit 布局的時候,參考值盡可能是一個明確值,盡可能不要設置參考的時候,再讓編譯器去幫我們計算值,我們可以盡可能多的告訴編譯器我們知道的事情。

四、其他考慮方向

1. SwiftUI

使用SwiftUI可以實時查看代碼顯示效果,並可以在不同設備上預覽效果。
使用 SwiftUI 可以提高開發效率。
SwiftUI 官方教程:Learn to Make Apps with SwiftUI

2. Swift的HotReload嘗試

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

五、參考學習網址


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM