亚洲精品久久久久久久久久久,亚洲国产精品一区二区制服,亚洲精品午夜精品,国产成人精品综合在线观看,最近2019中文字幕一页二页

您好,歡迎來(lái)電子發(fā)燒友網(wǎng)! ,新用戶?[免費(fèi)注冊(cè)]

您的位置:電子發(fā)燒友網(wǎng)>源碼下載>通訊/手機(jī)編程>

怎樣提高iOS工程打包的速度

大小:0.3 MB 人氣: 2017-09-25 需要積分:1

過(guò)慢的編譯速度有非常明顯的副作用。一方面,程序員在等待打包的過(guò)程中可能會(huì)分心,比如刷刷朋友圈,看條新聞等等。這種認(rèn)知上下文的切換會(huì)帶來(lái)很多隱形的時(shí)間浪費(fèi)。另一方面,大部分 app 都有自己的持續(xù)集成工具,如果打包速度太慢, 會(huì)影響整個(gè)團(tuán)隊(duì)的開(kāi)發(fā)進(jìn)度。

因此,本文會(huì)分別討論日常開(kāi)發(fā)和持續(xù)集成這兩種場(chǎng)景,分析打包速度慢的瓶頸所在,以及對(duì)應(yīng)的解決方案。利用這些方案,筆者成功的把公司 app 的持續(xù)集成時(shí)間從 45 min 成功的減少到 9 min,效率提升高達(dá) 80%,理論上打包速度可以提升 10 倍以上。如果用一句話總結(jié)就是:

在絕對(duì)的實(shí)力(硬件)面前,一切技巧(軟件)都是浮云

日常開(kāi)發(fā)

其實(shí)日常開(kāi)發(fā)的優(yōu)化空間并不大,因?yàn)槟J(rèn)情況下 Xcode 會(huì)使用上次編譯時(shí)留下的緩存,也就是所謂的增量編譯。因此,日常開(kāi)發(fā)的主要耗時(shí)由三部分構(gòu)成:

總耗時(shí) = 增量編譯 + 鏈接 + 生成調(diào)試信息(dSYM)

這里的增量編譯耗時(shí)比較短,即使是在我 14 年高配的 MacBook Pro(4核心,8 線程,2.5GHz i7 4870HQ,下文簡(jiǎn)稱 MBP) 上,也僅僅耗時(shí)十秒上下。我們的應(yīng)用代碼量大約一百多萬(wàn)行,業(yè)內(nèi)超過(guò)這個(gè)量級(jí)的應(yīng)用應(yīng)該不多。鏈接和生成調(diào)試信息各花費(fèi)不到 20s,因此一次增量的編譯的時(shí)間開(kāi)銷在半分鐘到一分鐘左右,我們逐個(gè)分析:

增量編譯: 因?yàn)楹臅r(shí)較短(大概十幾秒或者更少),幾乎不存在優(yōu)化的空間,但是非常容易惡化。因?yàn)橹挥蓄^文件不變的編譯單元才能被緩存,如果某個(gè)文件被 N 個(gè)文件引用,且這個(gè)文件的頭文件發(fā)生了變化,那么這 N 個(gè)文件都會(huì)重編譯。APP 的分層架構(gòu)一般都會(huì)做,但一個(gè)典型的誤區(qū)是在基礎(chǔ)庫(kù)的頭文件中使用宏定義,比如定義一些全局都可以讀取的常量,比如是否開(kāi)啟調(diào)試,服務(wù)器的地址等等。這些常量一旦改變(比如為了調(diào)試或者切換到某些分支)就會(huì)導(dǎo)致應(yīng)用重編譯。

鏈接:鏈接沒(méi)有緩存,而且只能用單核進(jìn)行,因此它的耗時(shí)主要取決于單核性能和磁盤(pán)讀寫(xiě)速度。考慮到我們的目標(biāo)文件一般都比較小,因此 4K 隨機(jī)讀寫(xiě)的性能應(yīng)該會(huì)更重要一些。

調(diào)試信息:日常開(kāi)發(fā)時(shí),并不需要生成 dSYM 文件,這個(gè)文件主要用于崩潰時(shí)查找調(diào)用棧,方便線上應(yīng)用進(jìn)行調(diào)試,而開(kāi)發(fā)過(guò)程中的崩潰可以直接在 Xcode 中看到,關(guān)閉這個(gè)功能 不會(huì)對(duì)開(kāi)發(fā)產(chǎn)生任何負(fù)面影響。

日常開(kāi)發(fā)的優(yōu)化空間不大,即使是龐大的項(xiàng)目,落后的機(jī)器性能,關(guān)閉 dSYM 以后也就耗時(shí) 30s 左右。相比之下,打包速度可以優(yōu)化和討論的地方就比較多了。

持續(xù)集成

在利用 Jenkins 等工具進(jìn)行持續(xù)集成時(shí),緩存不推薦被使用。這是因?yàn)樘O(píng)果的緩存不夠穩(wěn)定,在某些情況下還存在 bug。比如明明本地已經(jīng)修復(fù)了 bug,可以編譯通過(guò),但上次的編譯緩存沒(méi)有被正確清理,導(dǎo)致在打包機(jī)器上依然無(wú)法編譯通過(guò)?;蛘弑镜孛髅鲗?xiě)出了 bug,但同樣由于緩存問(wèn)題,打包機(jī)器依然可以編譯通過(guò)。

因此,無(wú)論是手動(dòng)刪除 Derived Data 文件夾,還是調(diào)用 xcodebuild clean 命令,都會(huì)把緩存清空。或者直接使用 xcodebuild archive,會(huì)自動(dòng)忽略緩存。每次都要全部重編譯是導(dǎo)致打包速度慢的根本原因。以我們的項(xiàng)目為例,總計(jì) 45min 的打包時(shí)間中,有 40min 都在執(zhí)行 xcodebuild 這一行命令。

使用 CCache 緩存

最自然的想法就是使用緩存了,既然蘋(píng)果的緩存不靠譜,那么就找一個(gè)靠譜的緩存,比如 CCache。它是基于編譯器層面的緩存,根據(jù)目前反饋的情況看,并不存在緩存不一致的問(wèn)題。根據(jù)筆者的實(shí)驗(yàn),使用 CCache 確實(shí)能夠較大幅度的提升打包速度,刪除緩存并使用 CCache 重編譯后,耗時(shí)只有十幾分鐘。

然而,CCache 最致命的問(wèn)題是不支持 PCH 文件和 Clang modules。PCH 的本意是優(yōu)化編譯時(shí)間,我們假設(shè)有一個(gè)頭文件 A 依賴了 M 個(gè)頭文件,其中每個(gè)被依賴的頭文件又依賴了 N 個(gè) 頭文件,如下圖所示:

怎樣提高iOS工程打包的速度

由于 #import 的本質(zhì)就是把被依賴頭文件的內(nèi)容拷貝到自己的頭文件中來(lái),因此頭文件 A 中實(shí)際上包含了 M * N 個(gè)頭文件的內(nèi)容,也就需要 M * N 次文件 IO 和相關(guān)處理。當(dāng)項(xiàng)目中每增加一個(gè)依賴頭文件 A 的文件,就會(huì)重復(fù)一次上述的 M * N 復(fù)雜度的過(guò)程。

PCH 文件的好處是,這個(gè)文件中的頭文件只會(huì)被編譯一次并緩存下來(lái),然后添加到項(xiàng)目中 所有 的頭文件中去。上述問(wèn)題倒是解決了,但很智障的一點(diǎn)是,所有文件都會(huì)隱式的依賴所有 PCH 中的文件,而真正需要被全局依賴的文件其實(shí)非常少。因此實(shí)際開(kāi)發(fā)中,更多的人會(huì)把 PCH 當(dāng)成一種快速 import 的手段,而非編譯性能的優(yōu)化。前文解釋過(guò),PCH 文件一旦發(fā)生修改,會(huì)導(dǎo)致徹徹底底,完完整整的項(xiàng)目重編譯,從而降低編譯速度。正是因?yàn)?PCH 的副作用甚至抵消了它帶來(lái)的優(yōu)化,蘋(píng)果已經(jīng)默認(rèn)不使用 PCH 文件了。

用來(lái)取代 PCH 的就是 Clang modules 技術(shù),對(duì)于開(kāi)啟了這一選項(xiàng)的項(xiàng)目,我們可以用@import 來(lái)替代過(guò)去的 #import,比如:

@import UIKit;

等價(jià)于

#import 《UIKit/UIKit.h》

拋開(kāi)自動(dòng)鏈接 framework 這些小特性不談,Clang modules 可以理解為模塊化的 PCH,它具備了 PCH 可以緩存頭文件的優(yōu)點(diǎn),同時(shí)提供了更細(xì)粒度的引用。

說(shuō)回到 CCache,由于它不支持 PCH 和 Clang modules,導(dǎo)致無(wú)法在我們的項(xiàng)目中應(yīng)用。即使可以用,也會(huì)拖累項(xiàng)目的技術(shù)升級(jí),以這種代價(jià)來(lái)?yè)Q取緩存,只怕是得不償失。

distcc

distcc 是一種分布式編譯工具,可以把需要被編譯的文件發(fā)送到其他機(jī)器上編譯,然后接收編譯產(chǎn)物。然而,經(jīng)過(guò)貼吧、貝聊、手Q 等應(yīng)用的多方實(shí)驗(yàn),發(fā)現(xiàn)并不適合 iOS 應(yīng)用。它的原理是多個(gè)客戶端共同編譯,但是絕大多數(shù)文件其實(shí)編譯時(shí)間非常短,并不值得通過(guò)網(wǎng)絡(luò)來(lái)回傳送,這種方案應(yīng)該只適合單個(gè)文件體量非常大的項(xiàng)目。在我們的項(xiàng)目中,使用 distcc大幅度增加了打包時(shí)間,大約耗時(shí) 1 小時(shí)左右。

定位瓶頸

在尋求外部工具無(wú)果后,筆者開(kāi)始嘗試著對(duì)編譯時(shí)間直接做優(yōu)化。為了搞清楚這 40min 究竟是如何花費(fèi)的,我首先對(duì) xcodebuild 的輸出結(jié)果進(jìn)行詳細(xì)分析。

使用過(guò) xcodebuild 命令的人都會(huì)知道,它的輸出結(jié)果對(duì)開(kāi)發(fā)者并不友好,幾乎沒(méi)有可讀性,好在還有 xcpretty 這個(gè)工具可以格式化它:

gem install xcpretty

通過(guò) gem 安裝后,只要把 xcodebuild 的輸出結(jié)果通過(guò)管道傳給 xcpretty 即可:

xcodebuild -scheme Release 。。. | xcpretty

非常好我支持^.^

(0) 0%

不好我反對(duì)

(0) 0%

      發(fā)表評(píng)論

      用戶評(píng)論
      評(píng)價(jià):好評(píng)中評(píng)差評(píng)

      發(fā)表評(píng)論,獲取積分! 請(qǐng)遵守相關(guān)規(guī)定!

      ?