Java 比 C++ 快?

鑑於近日有人把 http://kano.net/javabench/ 這篇笑話 post 出來,
說 Java 還是多少有比 C++ 快的地方,
因此還是特別抽空在這邊記一下,
免得以後還要重複講給人聽。

該 benchmark 有一個誤導人的地方,
就是在於「以 C++ 去配合 Java 的寫法」,
這是一個很輕易將實作經驗不足的人帶入自己謬論中的一個騙局。
C++ 在語言機制的彈性上遠比 Java 高,
我們並沒有必要去配合 Java 那樣寫,
事實上該 benchmark 中的 C++ code 很多都是 C code。
實際上 C++ 因為擁有 code generation 和操縱型別的能力,
這使得 C++ 確實有比 C 快的地方。
所以說該 benchmark 刻意把 C++ 程式寫爛也不為過。

除了上面描述的之外,
benchmark 本身也與 real-world application 差距甚遠,
準確性和公信力完全不足。
內容均是在比較同一語言設施的執行速度,
而且刻意忽略了 C++ 其實是可以組裝 garbage collector 的事實;
更完全忽略了 C++ 的 multi-paradigm 程式設計精神。
當我們試圖使用 C++ 和 Java 完成一套相同的軟體時,
Java 必須毫無選擇的使用 OOP,
但 C++ 卻有更廣泛的選擇;
因此不見得需要承擔 OO 機制帶來的效率損失。

已經有人將 C++ code 改寫,並且將原始碼放上網頁,
該網頁位於:http://cpp.student.utwente.nl/benchmark/,
原始碼位於:http://cpp.student.utwente.nl/benchmark/source.tar.gz。
目前現有的 benchmarks 不管有改過還是沒改過的,
都沒有附 sumcol 和 wc 這兩個測試項目的 input data。
我自己做了一個放在 https://it.muds.net/~uranus/java-vs-cxx/data.tbz,
同時我參考了 http://kano.net/javabench/ 提供的 console log,
下了完全相同的參數進行測試。
得到的結果放在 https://it.muds.net/~uranus/java-vs-cxx/log.tbz。

測試環境是用林餅幹學校的那台 ftp,
OS: FreeBSD 5.4-PRERELEASE
CPU: Pentium4 3.0EG (Prescott), HT enabled
MEM: 1608712192 (1534 MB)
測試結果是:

GCC 4.0 JDK 1.5
Ackermann 0:11.95 0:16.28
Fibonacci 0:09.78 0:18.26
Hash2 0:08.90 0:07.14
Hash 0:14.34 0:17.56
Heapsort 0:10.15 0:14.97
Matrix 0:07.81 0:10.78
Method call 0:02.89 0:02.50
Nested loop 0:06.24 0:14.26
Object creation 0:00.28 0:07.81
Random no. gen. 0:06.84 1:00.79
Sieve 0:06.69 0:10.53
String Concat. 0:01.12 0:04.44
Sumcol 0:00.14 0:01.58
Word count 0:00.09 0:01.43

g++ 下的參數是 -mtune=prescott -O3。
連 Intel C/C++ compiler 都還沒拿出來用就幾乎全贏了,
事實上那些改過的 C++ code 都還有最佳化空間在。
由此可以見得 Java 要贏真的是太困難了。 

何況這個測試還是用 Server JVM 來跟 C++ 拼的。
事實上 Server JVM 會非常用力的去吃 RAM,
還要下參數指定最大 mem 有多少讓它狂吃,
不夠的話就會丟出 out of memory 的 exception。
我是不清楚 Java 用 try catch 接到這個以後能怎樣重新要 memory 啦。
如果答案是不行的話,
那拿 Server JVM 來拼根本就是犯規。
mem 吃成這樣,
input 又沒有很大就會無法運作的程式,
根本就是等於已經 fail 掉一半的屍體。
這種東西就算是在學校交的作業,
助教還不見得肯給你 50 分。

這邊也放一個那篇笑話的 revisited website url:
http://www.freewebs.com/godaves/javabench_revisited/
不過這間網站的作者就沒有把 C++ 程式改得很好...