成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

淺談怎樣加快C++代碼的編譯速度

開(kāi)發(fā) 后端
C++代碼一直以其運(yùn)行時(shí)的高性能高調(diào)面對(duì)世人, 但是說(shuō)起編譯速度,卻只有低調(diào)的份了。本文介紹了加快C++編譯速度的方法,一起來(lái)看。

C++代碼一直以其運(yùn)行時(shí)的高性能高調(diào)面對(duì)世人, 但是說(shuō)起編譯速度,卻只有低調(diào)的份了。比如我現(xiàn)在工作的源代碼,哪怕使用Incredibuild調(diào)動(dòng)近百臺(tái)機(jī)子,一個(gè)完整的build也需要四個(gè)小時(shí),恐怖?。?!雖然平時(shí)開(kāi)發(fā)一般不需要在本地做完整的build,但編譯幾個(gè)相關(guān)的工程就夠你等上好一段時(shí)間的了(老外管這個(gè)叫monkey around,相當(dāng)形象)。想想若干年在一臺(tái)單核2.8GHZ上工作時(shí)的場(chǎng)景 - 面前放本書(shū),一點(diǎn)build按鈕,就低頭讀一會(huì)書(shū)~~~往事不堪回首。

可以想象,如果不加以重視,編譯速度極有可能會(huì)成為開(kāi)發(fā)過(guò)程中的一個(gè)瓶頸。那么,為什么C++它就編譯的這么慢呢?

我想最重要的一個(gè)原因應(yīng)該是C++基本的"頭文件-源文件"的編譯模型:

1.每個(gè)源文件作為一個(gè)編譯單元,可能會(huì)包含上百甚至上千個(gè)頭文件,而在每一個(gè)編譯單元,這些頭文件都會(huì)被從硬盤(pán)讀進(jìn)來(lái)一遍,然后被解析一遍。 

2.每個(gè)編譯單元都會(huì)產(chǎn)生一個(gè)obj文件,然后所以這些obj文件會(huì)被link到一起,并且這個(gè)過(guò)程很難并行。
這里,問(wèn)題在于無(wú)數(shù)頭文件的重復(fù)load與解析,以及密集的磁盤(pán)操作。

下面從各個(gè)角度給出一些加快編譯速度的做法,主要還是針對(duì)上面提出的這個(gè)關(guān)鍵問(wèn)題。

一、代碼角度

1、在頭文件中使用前置聲明,而不是直接包含頭文件。

不要以為你只是多加了一個(gè)頭文件,由于頭文件的"被包含"特性,這種效果可能會(huì)被無(wú)限放大。所以,要盡一切可能使頭文件精簡(jiǎn)。很多時(shí)候前置申明某個(gè)namespace中的類(lèi)會(huì)比較痛苦,而直接include會(huì)方便很多,千萬(wàn)要抵制住這種誘惑;類(lèi)的成員,函數(shù)參數(shù)等也盡量用引用,指針,為前置聲明創(chuàng)造條件。

2、使用Pimpl模式

Pimpl全稱(chēng)為Private Implementation。傳統(tǒng)的C++的類(lèi)的接口與實(shí)現(xiàn)是混淆在一起的,而Pimpl這種做法使得類(lèi)的接口與實(shí)現(xiàn)得以完全分離。如此,只要類(lèi)的公共接口保持不變,對(duì)類(lèi)實(shí)現(xiàn)的修改始終只需編譯該cpp;同時(shí),該類(lèi)提供給外界的頭文件也會(huì)精簡(jiǎn)許多。

3、高度模塊化

模塊化就是低耦合,就是盡可能的減少相互依賴(lài)。這里其實(shí)有兩個(gè)層面的意思。一是文件與文件之間,一個(gè)頭文件的變化,盡量不要引起其他文件的重新編譯;二是工程與工程之間,對(duì)一個(gè)工程的修改,盡量不要引起太多其他工程的編譯。這就要求頭文件,或者工程的內(nèi)容一定要單一,不要什么東西都往里面塞,從而引起不必要的依賴(lài)。這也可以說(shuō)是內(nèi)聚性吧。

以頭文件為例,不要把兩個(gè)不相關(guān)的類(lèi),或者沒(méi)什么聯(lián)系的宏定義放到一個(gè)頭文件里。內(nèi)容要盡量單一,從而不會(huì)使包含他們的文件包含了不需要的內(nèi)容。記得我們?cè)?jīng)做過(guò)這么一個(gè)事,把代碼中最"hot"的那些頭文件找出來(lái),然后分成多個(gè)獨(dú)立的小文件,效果相當(dāng)可觀。

其實(shí)我們?nèi)ツ曜鲞^(guò)的refactoring,把眾多DLL分離成UI與Core兩個(gè)部分,也是有著相同的效果的 - 提高開(kāi)發(fā)效率。

4、刪除冗余的頭文件

一些代碼經(jīng)過(guò)上十年的開(kāi)發(fā)與維護(hù),經(jīng)手的人無(wú)數(shù),很有可能出現(xiàn)包含了沒(méi)用的頭文件,或重復(fù)包含的現(xiàn)象,去掉這些冗余的include是相當(dāng)必要的。當(dāng)然,這主要是針對(duì)cpp的,因?yàn)閷?duì)于一個(gè)頭文件,其中的某個(gè)include是否冗余很難界定,得看是否在最終的編譯單元中用到了,而這樣又可能出現(xiàn)在一個(gè)編譯單元用到了,而在另外一個(gè)編譯單元中沒(méi)用到的情況。

之前曾寫(xiě)過(guò)一個(gè)Perl腳本用來(lái)自動(dòng)去除這些冗余的頭文件,在某個(gè)工程中竟然去掉多達(dá)了5000多個(gè)的include。

5、特別注意inline和template

這是C++中兩種比較"先進(jìn)"的機(jī)制,但是它們卻又強(qiáng)制我們?cè)陬^文件中包含實(shí)現(xiàn),這對(duì)增加頭文件的內(nèi)容,從而減慢編譯速度有著很大的貢獻(xiàn)。使用之前,權(quán)衡一下。

二、綜合技巧

1、預(yù)編譯頭文件(PCH)

把一些常用但不常改動(dòng)的頭文件放在預(yù)編譯頭文件中。這樣,至少在單個(gè)工程中你不需要在每個(gè)編譯單元里一遍又一遍的load與解析同一個(gè)頭文件了。

2、Unity Build

Unity Build做法很簡(jiǎn)單,把所有的cpp包含到一個(gè)cpp中(all.cpp) ,然后只編譯all.cpp。這樣我們就只有一個(gè)編譯單元,這意味著不需要重復(fù)load與解析同一個(gè)頭文件了,同時(shí)因?yàn)橹划a(chǎn)生一個(gè)obj文件,在鏈接的時(shí)候也不需要那么密集的磁盤(pán)操作了,估計(jì)能有10x的提高,看看這個(gè)視頻感受一下其做法與速度吧。

3、ccache

compiler cache, 通過(guò)cache上一次編譯的結(jié)果,使rebuild在保持結(jié)果相同的情況下,極大的提高速度。我們知道如果是build,系統(tǒng)會(huì)對(duì)比源代碼與目標(biāo)代碼的時(shí)間來(lái)決定是否要重新編譯某個(gè)文件,這個(gè)方法其實(shí)并不完全可靠(比如從svn上拿了上個(gè)版本的代碼),而ccache判斷的原則則是文件的內(nèi)容,相對(duì)來(lái)講要可靠的多。

很可惜的是,Visual Studio現(xiàn)在還不支持這個(gè)功能 - 其實(shí)完全可以加一個(gè)新的命令,比如cache build,介于build與rebuild之間,這樣,rebuild就可以基本不用了。

4、不要有太多的Additional Include Directories

編譯器定位你include的頭文件,是根據(jù)你提供的include directories進(jìn)行搜索的??梢韵胂?,如果你提供了100個(gè)包含目錄,而某個(gè)頭文件是在第100個(gè)目錄下,定位它的過(guò)程是非常痛苦的。組織好你的包含目錄,并盡量保持簡(jiǎn)潔。

三、編譯資源

要提高速度,要么減少任務(wù),要么加派人手,前面兩個(gè)方面講得都是減少任務(wù),而事實(shí)上,在提高編譯速度這塊,加派人手還是有著非常重要的作用的。

1、并行編譯

買(mǎi)個(gè)4核的,或者8核的cpu,每次一build,就是8個(gè)文件并行著編,那速度,看著都爽。 要是你們老板不同意,讓他讀讀這篇文章:Hardware is Cheap, Programmers are Expensive

2、更好的磁盤(pán)

我們知道,編譯速度慢很大一部分原因是磁盤(pán)操作,那么除了盡可能的減少磁盤(pán)操作,我們還可以做的就是加快磁盤(pán)速度。比如上面8個(gè)核一塊工作的時(shí)候,磁盤(pán)極有可能成為最大的瓶頸。買(mǎi)個(gè)15000轉(zhuǎn)的磁盤(pán),或者SSD,或者RAID0的,總之,越快越好。

3、分布式編譯

一臺(tái)機(jī)子的性能始終是有限的,利用網(wǎng)絡(luò)中空閑的cpu資源,以及專(zhuān)門(mén)用來(lái)編譯的build server來(lái)幫助你編譯才能從根本上解決我們編譯速度的問(wèn)題,想想原來(lái)要build 1個(gè)多小時(shí)工程的在2分鐘內(nèi)就能搞定,你就知道你一定不能沒(méi)有它 - Incredibuild。

4、并行,其實(shí)還可以這么做。

這是一個(gè)比較極端的情況,如果你用了Incredibuild,對(duì)最終的編譯速度還是不滿(mǎn)意,怎么辦?其實(shí)只要跳出思維的框架,編譯速度還是可以有質(zhì)的飛躍的 - 前提是你有足夠多的機(jī)器:

假設(shè)你有solution A和solution B,B依賴(lài)于A,所以必須在A之后Build B。其中A,B Build各需要1個(gè)小時(shí),那么總共要2個(gè)小時(shí)??墒荁一定要在A之后build嗎?跳出這個(gè)思維框架,你就有了下述方案:

◦同時(shí)開(kāi)始build A和B 。 

◦A的build成功,這里雖然B的build失敗了,但都只是失敗在最后的link上。

◦重新link B中的project。

這樣,通過(guò)讓A的build與B的編譯并行,最后link一下B中的project,整個(gè)編譯速度應(yīng)該能夠控制在1個(gè)小時(shí)15分鐘之內(nèi)。

原文鏈接:http://www.debuggingnow.com/blog/2010/01/how-to-improve-build-performance-of-cpp-code.html

希望本文能給你幫助。

【編輯推薦】

  1. 談?wù)凜++中三個(gè)容易混淆的概念
  2. C/C++中動(dòng)態(tài)鏈接庫(kù)的創(chuàng)建和調(diào)用
  3. VC++獲得當(dāng)前系統(tǒng)時(shí)間的幾種方案
  4. C++ Virtual詳解
  5. C++連接mysql數(shù)據(jù)庫(kù)的兩種方法
責(zé)任編輯:于鐵 來(lái)源: Dbger的博客
相關(guān)推薦

2020-05-26 13:25:00

語(yǔ)言編譯代碼

2010-01-22 13:20:27

C++代碼

2010-01-26 09:40:23

C++代碼

2009-07-01 16:01:58

JSP數(shù)據(jù)庫(kù)

2010-01-25 10:25:19

C++變量

2013-09-03 09:35:10

2010-01-22 18:33:17

C++編譯器

2012-09-18 13:26:39

CC++

2010-01-13 13:42:55

C++編譯器

2023-11-15 17:58:58

C++代碼

2010-01-20 14:35:55

C++調(diào)用

2009-08-07 17:32:17

C#編譯程序

2009-09-04 17:34:11

C#CC++

2010-01-26 10:01:17

學(xué)習(xí)C++

2011-04-08 09:52:44

C++C#DLL

2025-01-13 12:30:00

C++開(kāi)發(fā)編譯

2010-01-14 10:42:08

C++源代碼

2009-07-01 15:02:56

JSP程序JSP操作

2010-01-11 15:47:37

C++編譯

2010-01-12 17:26:37

C++編譯器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 日韩欧美第一页 | 精品国产乱码久久久久久影片 | 黄色网址在线免费播放 | 国产精品日产欧美久久久久 | 中文一级片 | 久久激情五月丁香伊人 | 国户精品久久久久久久久久久不卡 | 欧美在线小视频 | 国产一区91在线 | 国产精品久久久久久妇女6080 | 人人射人人草 | 999久久久久久久久6666 | 精品国产视频 | 欧美国产精品 | 欧美视频成人 | 亚洲电影一区二区三区 | 精品国产黄a∨片高清在线 www.一级片 国产欧美日韩综合精品一区二区 | 99久久精品免费看国产免费软件 | 999久久久久久久久 国产欧美在线观看 | 97精品一区二区 | 91天堂网 | 亚洲三级av | 亚洲午夜视频在线观看 | 午夜不卡福利视频 | 亚洲成人福利视频 | 一区二区三区免费观看 | av乱码 | 国产高清在线观看 | 成人精品国产 | 国产精品色综合 | 久久久妇女国产精品影视 | 日本特黄特色aaa大片免费 | 桃色五月 | 欧美精品久久久 | 成年人国产在线观看 | 国产成人在线一区二区 | 国产一区二区久久 | 在线亚洲欧美 | 国产欧美一区二区三区久久手机版 | 国产日产精品一区二区三区四区 | 99re在线视频|