2011年7月26日 星期二

轉載: Java與C++的比較

--------------------------------------------------------------------------------

作者 tinlans.bbs@whshs.cs.nccu.edu.tw (汀), 看板 Language
標題 Re: 請問為什麼 Java 比 C++ 更熱門?
時間 政大狂狷年少 (Thu Apr 14 04:44:10 2005)
來源 SimFarm!zoonews.ee.ntu!bbs.ee.ntu!news.ntu!Spring!ctu-peer!news.nctu!n
───────────────────────────────────────

※ 引述《HZYSoft.bbs@ptt.cc (PCMan 2004)》之銘言:
> http://kano.net/javabench/ 這篇就是在講 java 可以比 C++ 快的狀況
> 另外網路上還有非常多類似的 benchmark,理論不是絕對正確,有時應該讓數字說話
> 我以前看到一篇很完整的 benchmark,現在已經找不到了。
這篇很久之前我就讀過了,但是相當遺憾的,
那篇有非常非常多的問題在,相信你應該逛過它的 revisited 網站,
也看過 http://www.freewebs.com/godaves/javabench_revisited/ 這篇。
> 我自己是 C++ 的愛用者,沒在寫 java,不過我相信 java 確實不一定會比較慢
> C++ 不應該被神化,在很多地方他的效能確實不好,在一些應用上不見得強過 java
> 這個議題是相當具有爭議性的,ACM 上面也有論文在探討這個,可惜我看不到。
> 網路上充滿大量 benchmark,結論卻是很兩極化。身為 C++ 愛用者我們不能只看到
我們先來複習一下「Computer Architecture」課本,
benchmark 的準確性在 Computer Architecture: A Quantitative Approach 一書中,
被依照預測準確性由高至低分為五個層級:
1. real applications
2. modified (or scripted) applications
3. kernels
4. toy benchmarks
5. synthetic benchmarks
您所提及的網站中所列的 benchmark,大多位於第五個層級。


如果稍微觀察一下 benchmarks 的細部程式碼,
你會發現有非常多狀況是不切實際的。
譬如我們並不會把很大張的 hash table 擺在 local variable,
然後在 function 跑完之前花大量時間去解構它...
而在現實應用上將解構時間延遲至程式結束時是合理的,
因此 C++ 程式的設計者有充分的理由可以將需要存放大量物件的容器,
置於自由空間或是全域空間當中,避免解構動作持續發生,
亦可利用分期攤還原理,在某些條件發生時才選擇性解構物件,
或是在某些條件發生時預先建構一定數量的物件。

這樣的 benchmarks 讓人產生的主要盲點如下:

1. 與 real applications 的實際情形差異甚大。

benchmarks 本身是一群由純 coding 技巧即可完成的一群程式,
使試圖最佳化 C++ 程式碼者無法發揮 programming 的能力,
只能依據對語言本身的瞭解,以及最原始的 coding 方式去改善,
這主要的原因在於撰寫這些 benchmarks,
與 programming 的關係極小,
而 C++ 與 Java 的 programming paradigms 本身就大相逕庭,
強迫性的要求 C++ 程式與 Java 程式走相同路線。

2. 強調語言特性優劣,模糊問題重心。

刻意在兩個語言使用相同的寫法撰寫程式,
再搭配 time 指令的測量模糊問題重心,
迫使能透過 programming 提升效能的技術不受人注意,
該點已被我最後一個網址的老兄所破解,
他在合理的位置加上了測量時間的函式,
大大的降低了 programming 能力無法發揮的因素。

爭議極大的 method call 這項可說是集此兩點之大成。

除此之外,還有一些小細節被忽略了,
C++ 標準雖然規定的東西,遠比目前 java 實作出來的東西少,
但不代表用 C++ 開發程式的人就不能選用其它 library,
C++ 有很多東西藉由 template 化造就了「可組裝性」,
C++ 並不是沒有 GC 可用,只是 C++ 標準不內建 GC,
boehm-gc 就是有名的 C++ GC 之一,
因此一些故意欺負 C++ 沒 GC 的 benchmarks 簡直莫名其妙。

說到這邊,可能還會有人質疑,
那 Ackermann 和 Fibonacci 這種普普通通的怎麼 C++ 還會輸?
這東西表面上看起來的確讓人百思不解,
但是熟悉 gcc 發展歷程的人可能就不會奇怪了,
因為過去的 gcc 少做了非常非常多的事情。
我們來試試看現代的環境跑下來會是什麼結果。

測試環境:
OS: FreeBSD 5.4-PRERELEASE
CPU: Pentium4 3.0EG (Prescott), HT enabled
MEM: 1608712192 (1534 MB)
Compilers:
C++ : g++ version 4.0.0 20050409 (prerelease) [FreeBSD]
編譯參數 -mtune=prescott -O3
Java: J2SE version "1.5.0-p1"

來看看 Ackermann 的執行結果:
> time ./ackermann 13
Ack(3,13): 65533
11.973u 0.000s 0:11.97 100.0% 481+753k 0+0io 0pf+0w
> time java -server ackermann 13
Ack(3,13): 65533
15.388u 1.113s 0:16.34 100.9% 71+2356k 0+4io 0pf+0w

再來看看 Fibonacci:
> time ./fibo 45
1836311903
9.857u 0.000s 0:09.85 100.0% 481+276k 0+0io 0pf+0w

> time java -server fibo 45
1836311903
17.305u 1.131s 0:18.35 100.4% 70+1967k 0+4io 0pf+0w

我使用的是您所提供的網站所下載的原始碼,
原封不動直接編譯後獲得這樣的結果。
再次強調這只是解決一些人對這兩個 case 的疑慮,
因為這顯然是對 C++ 有利的程式,C++ 並沒有理由跑比較慢,
主要的原因是在於 C++ 編譯器在當時還不構成熟所造成的。

該篇文章中已經有許多數據不適用於現代環境,
最好還是照作者所說的:
I encourage you to download the source and/or the binaries and
perform the tests yourself, with your favorite compiler and on
your favorite platform.

實際跑跑看吧。

不過,我還是要強調,我 show 這兩個只是要說明過去 g++ 最佳化的能力不強,
並不是我認為這兩個 benchmarks 就具有代表性。
> 結論是 C++ 比較快的 benchmark,就堅信 C++ 一定比較快吧。那些一大堆 java 較快
> 的測試,固然有所偏差,結果還是值得參考,並不應該被忽略,事實上那是有可能的。
> GC 有時會比 C++ 重新建立物件要快,C++ 在物件初始化+配置記憶體的時候效能低落
> STL 的 stream 部份效能也不好。很多時候這和 library 的設計有關,我以前看的
> benchmark 找不到了,但是他測試了很多項目,其中有很多項 java 確實沒比較慢
> 而 C++ 會很強的情況下好像通常是用 Intel C++ compiler,否則差距不明顯
> 除了啟動超慢之外是大家公認之外,java 的執行效率確實並不一定會比較差。
> 目前確實有相當多的測試在探討這件事情,歡迎參考。

就我所知 C++ 的絕大多數潛在效率問題,
早已在 C++ Standard 問世之前就被人寫在 Inside The C++ Object Model 一書中,
而實際上在工業上會碰到而又容易被忽略的效率問題,
也大都被 Effective/More Effective/Exceptional/More Exceptional C++ 四書點出,
一個專業的 C++ programmer,
能夠很輕易的避開這些 benchmarks 中會發生的問題。

當我看到 Server VM 這種東西被搬出來的當下,
我立即察覺到了整件事的不公平性,
因為 C++ 可以與之抗衡的 meta-programming 技術,
幾乎都被離 real applications 太遠的 benchmarks 所壓抑,
迫使 C++ 必須使用與 Java 相同的 programming style 參與測試。
C++ Standard 的精神,以及 C++ 廣大的網路資源均遭到忽略,
造成拿有 GC 特性欺負保留 GC 給 library 實作的語言這種測試情形發生。

目前我個人時間也相當有限,
沒有時間去一一整理測試數據,
一一點明每個測試項目到底有哪些盲點。
就留給好奇的人自己 run 看看,
仔細分析看看這些 benchmarks 的 code 在真實軟體系統下會不會這樣寫了。
有問題再提出來一起討論看看。

--
Name: Tseng, Ling-hua E-mail Address: uranus@it.muds.net
School: National Chung Cheng University
Department: Computer Science and Information Engineering
Researching: Porting GCC and Implementing VLIW instruction scheduler in GCC
Homepage: https://it.muds.net/~uranus
--
╔═══╗ ┼────────────────────────╮
║狂狷 ║ │* Origin:[ 狂 狷 年 少 ] whshs.cs.nccu.edu.tw ╰─╮
║ 年少║ ┼╮ < IP:140.119.164.16 > ╰─╮
╚╦═╦╝ ╰ * From:220-143-196-90.dynamic.hinet.net
─╨─╨─ KGBBS ─ ◎ 遨翔"BBS"的狂狷不馴;屬於年少的輕狂色彩 ◎
--

沒有留言: