之前常聽說(shuō)C#和Java與C++的速度接近,更有甚者說(shuō)很多情況下他們都比C++快,而且舉出一大堆的范例(多是些IO操作,測(cè)量誤差超級(jí)大,因此很難令人信服),于是聽到很多人出來(lái)圓場(chǎng),說(shuō)對(duì)于語(yǔ)言內(nèi)建類型(整形、浮點(diǎn)型等),編譯成二進(jìn)制應(yīng)該相差不大,這似乎有些道理,但我仍然有些懷疑。

還曾經(jīng)聽不少人鼓吹過腳本,說(shuō)腳本程序比C++程序慢不了多少,有人甚至給10%,對(duì)此我不加評(píng)論了,看看這里的測(cè)試結(jié)果就一目了然。

下面有個(gè)浮點(diǎn)密集型的計(jì)算程序,沒有使用blitz++和MTL,很符合一般性應(yīng)用,如果用上他們那就不好說(shuō)怎么樣,因?yàn)橹饕呛虵ortran比科學(xué)計(jì)算速度時(shí)才用。已經(jīng)有人編碼測(cè)試了。
只講速度,如果再比內(nèi)存,其他幾種語(yǔ)言就沒有必要比下去了。


不同語(yǔ)言版本的代碼到原作者提供的地址去下載:http://files.cnblogs.com/miloyip/smallpt20100623.zip
下面是測(cè)試用的系統(tǒng)配置:

測(cè)試配置

  • 硬件: Intel Core i7 920@2.67Ghz(4 core, HyperThread), 12GB RAM
  • 操作系統(tǒng): Microsoft Windows 7 64-bit

測(cè)試名稱

編譯器/解譯器

編譯/運(yùn)行選項(xiàng)

VC++

Visual C++ 2008 (32-bit)

/Ox /Ob2 /Oi /Ot /GL /FD /MD /GS- /Gy /arch:SSE /fp:fast

VC++_OpenMP

Visual C++ 2008 (32-bit)

/Ox /Ob2 /Oi /Ot /GL /FD /MD /GS- /Gy /arch:SSE /fp:fast /openmp

IC++

Intel C++ Compiler (32-bit)

/Ox /Og /Ob2 /Oi /Ot /Qipo /GA /MD /GS- /Gy /arch:SSE2 /fp:fast /Zi /QxHost

IC++_OpenMP

Intel C++ Compiler (32-bit)

/Ox /Og /Ob2 /Oi /Ot /Qipo /GA /MD /GS- /Gy /arch:SSE2 /fp:fast /Zi /QxHost /Qopenmp

GCC

GCC 4.3.4 in Cygwin (32-bit)

-O3 -march=native -ffast-math

GCC_OpenMP

GCC 4.3.4 in Cygwin (32-bit)

-O3 -march=native -ffast-math -fopenmp

C++/CLI

Visual C++ 2008 (32-bit), .Net Framework 3.5

/Ox /Ob2 /Oi /Ot /GL /FD /MD /GS- /fp:fast /Zi /clr /TP

C++/CLI_OpenMP

Visual C++ 2008 (32-bit), .Net Framework 3.5

/Ox /Ob2 /Oi /Ot /GL /FD /MD /GS- /fp:fast /Zi /clr /TP /openmp

C#

Visual C# 2008 (32-bit), .Net Framework 3.5

 

*C#_outref

Visual C# 2008 (32-bit), .Net Framework 3.5

 

F#

F# 2.0 (32-bit), .Net Framework 3.5

 

Java

Java SE 1.6.0_17

-server

JsChrome

Chrome 5.0.375.86

 

JsFirefox

Firefox 3.6

 

LuaJIT

LuaJIT 2.0.0-beta4 (32-bit)

 

Lua

LuaJIT (32-bit)

-joff

Python

Python 3.1.2 (32-bit)

 

*IronPython

IronPython 2.6 for .Net 4

 

*Jython

Jython 2.5.1

 

Ruby

Ruby 1.9.1p378

 

渲染的解像度為256x256,每象素作100次采樣。

結(jié)果及分析

下表中預(yù)設(shè)的相對(duì)時(shí)間以最快的單線程測(cè)試(IC++)作基準(zhǔn),用鼠標(biāo)按列可改變基準(zhǔn)。由于Ruby運(yùn)行時(shí)間太長(zhǎng),只每象素作4次采樣,把時(shí)間乘上25。另 外,因?yàn)楦鳒y(cè)試的渲染時(shí)間相差很遠(yuǎn),所以用了兩個(gè)棒形圖去顯示數(shù)據(jù),分別顯示時(shí)間少于4000秒和少于60秒的測(cè)試(Ruby4000秒以外,不予顯 )

Test

Time(sec)

Relative time

IC++_OpenMP

2.861

0.19x

VC++_OpenMP

3.140

0.21x

GCC_OpenMP

3.359

0.23x

C++/CLI_OpenMP

5.147

0.35x

IC++

14.761

1.00x

VC++

17.632

1.19x

GCC

19.500

1.32x

C++/CLI

27.634

1.87x

Java

30.527

2.07x

C#_outref

44.220

3.00x

F#

47.172

3.20x

C#

48.194

3.26x

JsChrome

237.880

16.12x

LuaJIT

829.777

56.21x

Lua

1,227.656

83.17x

IronPython

2,921.573

197.93x

JsFirefox

3,588.778

243.13x

Python

3,920.556

265.60x

Jython

6,211.550

420.81x

Ruby

77,859.653

5,274.69x

C++/.Net/Java組別

靜態(tài)語(yǔ)言和動(dòng)態(tài)語(yǔ)言在此測(cè)試下的性能不在同一數(shù)量級(jí)。先比較靜態(tài)語(yǔ)言。

C++.Net的測(cè)試結(jié)果和上一篇博文相若,而C#F#無(wú)顯著區(qū)別。但是,C++/CLI雖然同樣產(chǎn)生IL,于括管的.Net平臺(tái)上執(zhí)行,其渲染時(shí)間 卻只是C#/F#55%左右。為什么呢?使用ildasm去反匯編C++/CLIC#的可執(zhí)行文件后,可以發(fā)現(xiàn),程序的熱點(diǎn)函數(shù) Sphere.Intersect()在兩個(gè)版本中,C++/CLI版本的代碼大小(code size)201字節(jié), C#則為125字節(jié)! C++/CLI版本在編譯時(shí),已把函數(shù)內(nèi)所有Vec類的方法調(diào)用全部?jī)?nèi)聯(lián),而C#版本則使用callvirt調(diào)用Vec的方法。估計(jì)JIT沒有把這函數(shù)進(jìn) 行內(nèi)聯(lián),做成這個(gè)性能差異。另外,C++/CLI版本使用了值類型,并使用指針(代碼中為引用)托管代碼(C++/CLI)的渲染時(shí)間,僅為原生非括管代碼(IC++)1.91倍,個(gè)人覺得.NetJIT已經(jīng)非常不錯(cuò)。

另一方面,Java的性能表現(xiàn)非常突出,只比C++/CLI稍慢一點(diǎn),Java版本的渲染時(shí)間為C#/F#65%左右。以前一直認(rèn)為,C#不少設(shè)計(jì)會(huì)使其性能高于Java,例如C#的方法預(yù)設(shè)為非虛,Java則預(yù)設(shè)為虛;又例如C#支持struct作值類型(value type)Java則只有class引用類型(reference type),后者必須使用GC。但是,這個(gè)測(cè)試顯示,Java VM應(yīng)該在JIT中做了大量?jī)?yōu)化,估計(jì)也應(yīng)用了內(nèi)聯(lián),才能使其性能逼近C++/CLI

C++方面,Intel C++編譯器最快,Visual C++慢一點(diǎn)點(diǎn)(1.19x)GCC再慢一點(diǎn)點(diǎn)(1.32x)。這結(jié)果符合本人預(yù)期。 Intel C++OpenMP版本和單線程比較,達(dá)5.16加速比(speedup),對(duì)于4Hyper Threading來(lái)說(shuō)算是不錯(cuò)的結(jié)果。讀者若有興趣,也可以自行測(cè)試C# 4.0的并行新特性。

動(dòng)態(tài)語(yǔ)言組別

首先,要說(shuō)一句,Google太強(qiáng)了,難以想像JsChome的渲染時(shí)間僅是IC++16.12倍,C#4.94倍。

以下比較各動(dòng)態(tài)語(yǔ)言的相對(duì)時(shí)間,以JsChrome為基準(zhǔn)。 ChromeV8 JavaScript引擎(1.00x)大幅拋離FirefoxSpiderMonkey引擎(15.09x)。而LuaJIT(3.49x)Lua(5.16x)則排第二和第三名。 LuaJIT版本是沒有JIT68%,并沒有想像中的快,但是也比Python(16.48x)快得多。曾聽說(shuō)過Ruby有效能問題,沒想到問題竟然如此嚴(yán)重(327.31x),其渲染時(shí)間差不多是Python20倍.