当前位置:早雪网网络学院编程文档其他语言 → 利用pre-compiled headers技术以加速编译速度(一)

利用pre-compiled headers技术以加速编译速度(一)

减小字体 增大字体 作者:未知  来源:supcode.com收集整理  发布时间:2005-7-1 14:53:37
<初见pre-compiled headers技术>

    过去我们撰写C/C++程序时,每个档案都必须利用编译器指令 #include 引入许多的系统标头文件才能够使程序顺利编译,接着经由连结产生执行档。假如我们的Project(程序项目)存有两个档案a.cpp以及b.cpp,当我们在a.cpp里面用到getch()这个函式,我们就必须在使用a.cpp的开头处写着: #include <conio.h>
    否则编译器一定告诉我们这个函式没有定义。同样地,即使b.cpp 这个档案和a.cpp同属一个Project之中,档案里面只要有用到getch()这个函式,一样得在b.cpp的开头处写着: #include <conio.h>
    当编译器编译a.cpp的时候,编译器必须编译conio.h一次,接着编译b.cpp的时候,同样必须重新编译conio.h一次。因此,一旦a.cpp引入更多和b.cpp相同的标头档,也就代表编译器将浪费许多时间在编译同样的标头档上。举例来说,如果我们的Project里面有十个cpp档同时引入相同的标头档,那幺就代表编译的时间有9/10都因为被用来编译相同的标头档而浪费掉了。因此BCB引进了pre-compiled headers技术,主要就是为了解决这个会使得编译器做过多重复的编译工作而导致编译过程漫长的问题。
    所谓的pre-compiled headers技术,在笔者的记忆中是从BCB 3.0开始引进的概念,其实概念很简单,就是”预先编译标头档”的意思。以我们拿刚刚提到的例子来说,编译器第一次编译a.cpp的时候,就会因为使用pre-compiled headers技术,会先把conio.h的编译结果先”cache”起来,然后等到待会编译b.cpp的时候,编译器会发现conio.h已经先被编译过了,因此编译器就直接把刚刚cache起来的conio.h编译结果直接拿来使用,这样一来就省掉了了大量的编译时间,而程序设计师就可以从此向冗长的编译过程说bye bye。
    在BCB之中,pre-compiled headers技术是透过编译器指令#pragma hdrstop来达成,从BCB的help里面得知,出现在这个编译器指令之前的标头文件即代表告知编译器要使用pre-compiled headers技术来加速编译。但是事情并没有我们想象的那幺单纯,所以接下来笔者会花很长的篇幅来探讨编译器指令#pragma hdrstop对编译效能所带来的影响。

<pre-compiled headers技术对编译速度的影响 - 1>

    首先,我们先按照<前置作业>所提到的方式,删掉所有在编译过程之中产生的所有档案(*.exe 、 *.obj 、 *.tds ,请注意 , *.tds必须关掉整个Project之后才能删除,也请大家先删除BCB所在目录的Lib子目录里面的*.csm以及*.#??,『?』代表是一个0~9的数字)。
    接下来,我们做个简单的测试,用干净的程序原始码(就是尚未编译过的原始码)来做编译速度的测试,以下的数据以笔者的计算机输出结果为基准,笔者的计算机配备为: Intel PIII 450 、 胜创PC100 128MB RAM 、华硕P2B主机板、操作系统是Windows 2000 Professional:

程序代码1:
#include <iostream.h>
#include <vcl.h>
#pragma hdrstop
#pragma argsused
int main(int argc, char* argv[])
{
    cout << "Hello World" ;
    return 0;
}

测试结果1:

使用build 使用make
编译次数 编译行数 编译时间 编译次数 编译行数 编译时间
第一次 419266 7.90 第一次 419266 7.73
第二次以后 510638 8.48 第二次以后 0  0.14


程序代码2:
#pragma hdrstop
#include <iostream.h>
#include <vcl.h>
#pragma argsused
int main(int argc, char* argv[])
{
    cout << "Hello World" ;
    return 0;
}
斜体字部分为与程序代码1不同之处

测试结果2:


使用build 使用make
编译次数 编译行数 编译时间 编译次数 编译行数 编译时间
第一次 419266 5.60 第一次 419266 5.86
第二次以后 510638 4.42 第二次以后 0 0.15

    提醒读者一点,空白行也算被编译器在编译行数中,所以大家的测试结果在编译行数上可能会有些微的差距。

从上面的列表可以得到以下结论:
对这两组测试程序而言,第一次编译的时候不管用make或是build,其编译速度几乎没差别。但是第二次以后的编译,使用make的编译速度压倒性的快,而且快很多,原因请读者参照一些介绍make的相关书籍。在这里笔者介绍O’Reilly (台湾欧来礼) 出版的Managing Project with make,这本书在台湾欧来礼的网站www.oreilly.com.tw似乎有看到会出现中文本的消息。
     
把标头文件放在编译器指令 #pragma hdrstop之前在第一次编译所花的时间要比把标头文件放在编译器指令 #pragma hdrstop之后要久。咦? 之前不是还提到利用pre-compiled headers技术会加快编译速度,怎幺经过实验之后发现竟然编译速度变慢了呢? 要找寻原因,我们可以使用windows开始菜单里面的 搜寻/档案或资料夹 功能,搜寻BCB所在目录,将搜寻日期限定为您计算机上目前的日期,读者就可以发现,一旦您把标头文件放在编译器指令 #pragma hdrstop之前,在BCB所在目录下的Lib子目录就会出现vcl50.#00以及vcl50.csm两个档案,而且档案的size还蛮大的,但是如果把标头文件放在编译器指令 #pragma hdrstop之后,这两个档案并不会出现(如果读者在测试的时候先测试程序代码1,再测试程序代码2,那幺这两个档案依旧会出现,因为这两个档案并不会因为重新打开Project或是重新开启BCB而被删除,因此读者看到的可能是前次编译所产生的vcl50.#00以及vcl50.csm)。
    如此一来,我们可以大胆地推测:之所以把标头文件放在编译器指令 #pragma hdrstop之前在第一次编译所花的时间会比较长,是因为编译器花了额外的功夫去产生这两个档案。因为编译后所显示的编译时间并非只有单纯的编译时间,还包括了连结目的档以产生执行档所耗费的时间。精确的说,应该是『从开始编译原始码到产生最后的执行档总共所花的时间』,所以前面的测试数据会给大家一种『使用pre-compiled headers技术反而会减慢编译速度』的假象。

    读者在前面所看到测试结果1所得的数据,是笔者每次测试过后,除了删掉编译时产生的*.obj 、 *.tds 、 *.exe档之外,还外加删掉vcl50.#00以及vcl50.csm两个档案所测得。如果在测试程序代码1/使用make的时候,笔者没有删除测试程序代码1/使用build的时候所产生vcl50.#00以及vcl50.csm这两个档案,则测试结果1的数据会变成:
测试结果3:

使用build 使用make
编译次数 编译行数 编译时间 编译次数 编译行数 编译时间
第一次 201723 13.57 第一次 17 1.87
第二次以后 201723 13.98 第二次以后 0 0.14


    是什幺原因导致结果有所差异呢? 因为笔

[1] [2]  下一页


Tags:利用,pre,compiled,headers,技术,加速,编译,速度
[数据载入中...] [返回上一页] [打 印]