之前常聽(tīng)說(shuō)C#和Java與C++的速度接近,更有甚者說(shuō)很多情況下他們都比C++快,而且舉出一大堆的范例(多是些IO操作,測(cè)量誤差超級(jí)大,因此很難令人信服),于是聽(tīng)到很多人出來(lái)圓場(chǎng),說(shuō)對(duì)于語(yǔ)言?xún)?nèi)建類(lèi)型(整形、浮點(diǎn)型等),編譯成二進(jìn)制應(yīng)該相差不大,這似乎有些道理,但我仍然有些懷疑。
還曾經(jīng)聽(tīng)不少人鼓吹過(guò)腳本,說(shuō)腳本程序比C++程序慢不了多少,有人甚至給10%,對(duì)此我不加評(píng)論了,看看這里的測(cè)試結(jié)果就一目了然。
下面有個(gè)浮點(diǎn)密集型的計(jì)算程序,沒(méi)有使用blitz++和MTL,很符合一般性應(yīng)用,如果用上他們那就不好說(shuō)怎么樣,因?yàn)橹饕呛虵ortran比科學(xué)計(jì)算速度時(shí)才用。已經(jīng)有人編碼測(cè)試了。
只講速度,如果再比內(nèi)存,其他幾種語(yǔ)言就沒(méi)有必要比下去了。
不同語(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è)試名稱(chēng)
|
編譯器/解譯器
|
編譯/運(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è)試(Ruby是4000秒以外,不予顯 示)。
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++/CLI和C#的可執(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類(lèi)的方法調(diào)用全部?jī)?nèi)聯(lián),而C#版本則使用callvirt調(diào)用Vec的方法。估計(jì)JIT沒(méi)有把這函數(shù)進(jìn) 行內(nèi)聯(lián),做成這個(gè)性能差異。另外,C++/CLI版本使用了值類(lèi)型,并使用指針(代碼中為引用)托管代碼(C++/CLI)的渲染時(shí)間,僅為原生非括管代碼(IC++)的1.91倍,個(gè)人覺(jué)得.Net的JIT已經(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作值類(lèi)型(value type),Java則只有class引用類(lèi)型(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ì)于4核Hyper 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)。 Chrome的V8 JavaScript引擎(1.00x)大幅拋離Firefox的SpiderMonkey引擎(15.09x)。而LuaJIT(3.49x)和Lua(5.16x)則排第二和第三名。 Lua的JIT版本是沒(méi)有JIT的68%,并沒(méi)有想像中的快,但是也比Python(16.48x)快得多。曾聽(tīng)說(shuō)過(guò)Ruby有效能問(wèn)題,沒(méi)想到問(wèn)題竟然如此嚴(yán)重(327.31x),其渲染時(shí)間差不多是Python的20倍.