Win32 FPC/Delphi/BCC/MinGW/VC
编译器性能对比测试
(Matrix Multiplication)
0
序
本文的观点与结论仅仅包括作者本人在特定软件、硬件环境下的真实试验过程得到。本文仅仅提供一种客观的参考建议,不含有任何涉及褒贬的叙述目的,不含有任何绝对正确的担保责任,不希望引起更多的争论。除标注引用部分之外,均为原创文献。
1
引言
在
Win32
系统下,什么
Pascal
编译器是最优秀的?什么
C
编译器是最优秀的?在不同的工程项目中,应该如何选择最恰当的?如果你愿意打开
Google
搜索
”language benchmark”
,就会得到很多类似问题的答案(
http://shootout.alioth.debian.org/, http://dada.perl.it/shootout/, ...
)等。
长久以来,我需要同时使用多种编程语言和多种开发环境。从最早
1995
年的
Delphi 1.0
开始,这个运行在当时的
Windows 3.1
系统之上的
RAD
软件使我成为
Delphi
和
Object Pascal
语言的忠实
Fans
;其后由于工作的原因转而使用
C/C++
编程,熟悉了
Win32
平台之上的一些
C/C++
开发环境与编译器;近两年(抱歉,我发现新事物的速度是如此之慢)发现了
FreePascal
,一个相当不错的跨平台
Pascal
编译器,支持多种
Pascal
方言(当然包括
Delphi
语法),尤其是随着
FreePascal 2.0
的发布,渐渐使其具备了生产环境的能力。
我主要的工作领域在基础级的服务器软件设计,所以
Java
和
C#
等基于
VM
的语言由于运行效率和交互环境限制的原因没有进入过我的视线,故我对其了解甚少。
在
Win32
系统下,我们可以接触到的不同的
C/Pascal
编译器,有免费开源的,也有昂贵的商业产品,为了安慰开发者有时手足无措的选择(当然,绑死在一个固定产品的开发者显然不需要顾虑这些)和满足开发者的好奇关注,网上出现了专门针对编程语言和编译器性能的对比测试,论坛上为了同样的论题也引发了大量的争论。从“
The Great Win32 Computer Language Shootout
”(
http://dada.perl.it/shootout/
)站点,我也得到了相应的信息,但是直觉告诉我,这些数据不一定是准确的,因为性能数据的年限显得有些旧,
MinGW32
、
VC
、
FreePascal
的用于测试的编译器版本很旧,而且这些产品在后续的版本都出现了大幅度的升级,如
FreePascal 1.04
升级到了
2.0.2
,
MinGW
从
2.95
升级到今日的
3.4.x
,
VC6
也升级到了
VC8
,原有的数据已经不能说明当今的情况。
在最近的一段时间里,我需要评估
FreePascal
的能力。
FreePascal
(
http://www.freepascal.org
)已经被移植到几乎所有的主流平台之上,加之与
Object Pascal
语法和
RTL
的优秀兼容性,完全符合一次编写,到处编译运行的特征,以及具备在跨平台的服务器端系统开发中接近准入的能力。
2
环境
那么,我尝试重现其中的部分测试过程,来对最新的编译器技术作以测试。测试的编译器环境包括
FPC(FreePascal)/Delphi/BCC/MinGW/VC
,它们各自的版本信息如下:
--fpc
Free Pascal Compiler version 2.0.2 [2005/11/26] for i386
Copyright (c) 1993-2005 by Florian Klaempfl
--dcc32(Delphi7)
Borland Delphi Version 15.0
Copyright (c) 1983,2002 Borland Software Corporation
--bcc32
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
--gcc
gcc (GCC) 3.4.2 (mingw-special)
Copyright (C) 2004 Free Software Foundation, Inc.
--cl(VC2005)
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
它们中间包括
2
个
Pascal
编译器
fpc,dcc32
和
3
个
C
编译器
bcc32,gcc,cl
,并且
fpc,bcc32
和
gcc-mingw
都是免费自由下载使用的软件,可以从
Internet
之上直接获得。
采用的测试方案是来自于
“
The Great Win32 Computer Language Shootout
”
的“
Matrix Multiplication
”项目,参照
http://dada.perl.it/shootout/matrix.html
。
其中
FreePascal
和
Delphi
采用相同的源代码文件
matrix.pas
,来自于
http://dada.perl.it/shootout/matrix.delphi.html
。
BCC
、
MinGW
和
VC
采用相同的源代码文件
matrix.c
,来自于
http://dada.perl.it/shootout/matrix.vc.html
。并针对每一种编译器使用多种不同的编译参数来生成多个待测程序。
虽然是完成相同的计算,得到相同的测试结果,但是
Pascal
语言和
C
语言之间的语法差异使得它们之间相互的对比似乎有失公平,是的,不过可以忽略不计。
硬件的测试环境为
ThinkPad X31 267239C (PM 1.5G, 768M, 80G. Windows XP SP2)
,并且关闭所有运行中的应用程序。
3
方法
通过编写一个独立的计时工具软件来完成对之前编译结果的测试工作,我简单的写了一个小工具
(timer)
,它很简陋,但是确实可靠,并且精度足够。
timer
工具用于测量一个控制台应用程序的运行时间,待测试的控制台程序是由
timer
工具启动,并且采样了从创建待测试进程
(CreateProcess)
直到待测试进程运行完毕
(WaitForSingleObject(hProcess, INFINITE)
跳出
)
的时间间隔,其中包括了创建进程时间和待测试程序的启动代码与退出代码时间。
为了降低测试的误差,
timer
工具将待测试进程的优先级类别提升为
HIGH_PRIORITY_CLASS
,以防止当前大部分运行中进程的干扰。另外,
timer
工具会首先不计时运行一次待测试程序,使得后续测试都有
Cache
载入的效应,再连续计时运行待测试程序
5
次,求得
5
次耗时的平均值作为最终成绩,尽可能减少误差的影响。
timer
工具的使用方法为
: timer <arguments> ...
,后续的参数被当作新的命令行创建被计时受控的进程,如
timer program.exe xx yy zz
等等,很简单,不是吗?不过需要注意一点,待测的程序必须是控制台程序,而且不能有运行中来自键盘的输入(测试性能时怎么可能会有呢?)。在计时运行过程中,屏蔽了创建进程的
StdIn
和
StdOut
以消除潜在额外的负荷。
timer
工具的完整源代码如下
(timer.cpp)
,
Eclipse/CDT 3.1+MinGW 3.4.2
测试通过。
/* timer.cpp: (c) yaoyong 2006, eclipse/cdt, mingw32 */
#include
<iostream>
#include
<string>
#include
<vector>
#include
<algorithm>
#include
<numeric>
#include
<windows.h>
using
namespace
std;
int64_t perf_freq, perf_c_start, perf_c_stop;
string cmd_line;
inline
void
timer_start(
void
)
{
QueryPerformanceCounter((_LARGE_INTEGER *)&perf_c_start);
}
inline
int
timer_stop(
void
)
{
QueryPerformanceCounter((_LARGE_INTEGER *)