??最近部門有一個(gè)關(guān)于代碼編譯效率的問(wèn)題需要解決,具體背景就不方便介紹了善绎。下面我們以一個(gè)例子說(shuō)明钦铺。
?? 假設(shè)你是一個(gè)linux內(nèi)核的開(kāi)發(fā)著殊校,據(jù)我所知2.6版本的內(nèi)核代碼就達(dá)260多萬(wàn)行(見(jiàn)下圖)张漂。
??假設(shè)你有一個(gè)submit晶默,需要驗(yàn)證其正確性即需要將所有的代碼編譯一邊,那么需要多少時(shí)間呢航攒?(上學(xué)時(shí)嘗試過(guò)2.6的內(nèi)核磺陡,大約一個(gè)小時(shí)。這是不可想象的D蟆币他!。不過(guò)話說(shuō)回來(lái)現(xiàn)在的電腦性能提高了好多憔狞,最近給新買的電腦裝Ubuntu系統(tǒng)蝴悉,居然只使用了不到5分鐘)。那么如何解決耗時(shí)問(wèn)題呢瘾敢?下面我們通過(guò)實(shí)例進(jìn)行分析拍冠。
?? 代碼分為cpp/c文件和h文件,其中我們把cpp/c稱為一個(gè)編譯單元簇抵,h文件當(dāng)include后實(shí)際上只是提供一個(gè)前向聲明的作用(可以使用GCC/G++ -E 通過(guò)展示預(yù)處理來(lái)觀察)庆杜。下面提供一個(gè)簡(jiǎn)單的makefile展示下程序的編譯過(guò)程
objects = main.o kbd.o command.o display.o
edit : $(objects)
?? cc -o edit $(objects)
main.o : main.c defs.h
?? cc -c main.c -o main.o
kbd.o : kbd.c defs.h command.h
?? cc -c kbd.c -o kbd.o
command.o : command.c defs.h command.h
?? cc -c command.c -o command.o
display.o : display.c defs.h buffer.h
.PHONY : clean
clean :
?? rm edit $(objects)
??上述makefile表示我們需要產(chǎn)出一個(gè)名叫edit的可執(zhí)行文件,其依賴 main.o kbd.o command.o display.o碟摆,如果其中有一個(gè)依賴找不著晃财,makefile會(huì)通過(guò)缺少文件的產(chǎn)生規(guī)則生成該文件。例如main.o依賴main.c和defs.h, 如果main.o 不存在則會(huì)通過(guò):cc -c main.c -o main.o(表示一個(gè)編譯過(guò)程)得到典蜕,一次類推断盛。依賴的object都存在了雏逾,則通過(guò):cc -o edit $(objects) 鏈接得到可執(zhí)行文件。上述makefile明確的向我們展示了程序的編譯和鏈接過(guò)程郑临。編譯過(guò)程中我們經(jīng)常發(fā)現(xiàn)栖博,程序是一個(gè)增量編譯過(guò)程。實(shí)際上makefile在工作時(shí)為了加快編譯速度厢洞,會(huì)檢測(cè)cpp/c及其依賴文件和可鏈接文件的時(shí)間戳仇让,如果鏈接文件的時(shí)間戳比編譯單元新則不會(huì)重新編譯,這也就是程序增量編譯的原因躺翻。(上述makefile比較簡(jiǎn)單丧叽,沒(méi)有展示所有編譯過(guò)程,有興趣的可以查找資料學(xué)習(xí)下公你。雖說(shuō)現(xiàn)在我們已經(jīng)很少使用makefile來(lái)管理工程踊淳,但是只有了解其工作原理這樣你才能完全理解一個(gè)完整編譯過(guò)程~~~)。
?? 預(yù)處理 -----> 編譯------>匯編----->鏈接 陕靠。
??可執(zhí)行文件的產(chǎn)生一般經(jīng)過(guò)了上面的幾個(gè)過(guò)程迂尝,不過(guò)我們可以將其簡(jiǎn)化為編譯和鏈接兩個(gè)過(guò)程(makefile中已經(jīng)明確了上述兩個(gè)過(guò)程)。如果你需要加快可執(zhí)行文件產(chǎn)生過(guò)程剪芥,除了一般的ccache垄开,減少物理依賴等這種“吹毛求疵”的方法外還有沒(méi)有其他方式呢?這也就是本次需要討論的問(wèn)題税肪。
??我們明確了程序的編譯主要分為編譯和鏈接兩個(gè)階段溉躲,最為耗時(shí)的過(guò)程為編譯,所以要大幅度的提高編譯效率也就只能在該階段找突破益兄。那么我們的解決辦法是什么呢锻梳?"分布式"編譯即:將工程打散,將原來(lái)的串行改為并行净捅,如下圖所示:
??如上我們將浩大的工程拆成若該個(gè)微小的模塊疑枯,使用多臺(tái)機(jī)器并行編譯最后再統(tǒng)一在中心節(jié)點(diǎn)機(jī)器進(jìn)行鏈接、執(zhí)行灸叼,從而成倍的減少編譯耗時(shí)神汹。工作原理比較簡(jiǎn)單,通過(guò)編寫簡(jiǎn)單的Cmake文件和shell我們就實(shí)現(xiàn)上述思想古今。好了就這么多了屁魏,如果小伙伴有其它好方法可以可以一起討論下∽叫龋~~~