※ 引述《lgd1008 (lgd1008)》之銘言:
: : Java的效能美夢已經被吹噓到讓許多人忽略了計算機結構上的根本道理了。
: 不要只把 VM, GC 算進 overhead, 而不同時考慮他們可能對效能產生的幫助,
請試舉一例VM/GC對整體效能有幫助的例子。
: CPU的指令己是VC++執行時的全部, 但並非 .net, Java執行時的全部
這句話在我聽來相當不切實際,莫非.net/java不需要CPU?
凡是以CPU執行的,最後都是要用CPU的指令去跑的,
中間多做事情只是多花時間的,跑愈多指令去做一件事只是用更多時間去完成那事。
就假設所有指令都可以在單個clock內完成的RISC來說,執行每個指令都只要1 cycle,
所有演算法的時間複雜度直接與跑了多少個CPU指令在統計上就是絕對正相關。
你可以爭論說,GC可以在某種程度上改善你跑的演算法花在釋放記憶體的代價;
但是整體觀之,那不過是朝三暮四的效果,該做的事情最後還是都要做,而且付出了
更大的效能代價去做,因為你還要多花時間去爬垃圾堆,看是不是該清垃圾了,
而不是在垃圾丟出來時就馬上清掉。
IKVM.net的作者都會常常關注Java VM JIT生出來的code與他的IKVM將Java bytecode
轉成IL code再生成原生code後的指令數差距、對CPU管線利用率的影響了。
: 會拿看起來 VM, GC 是 overhead 的情況去看 Java, .net
: 那怎麼不拿非 VM, GC 存在不可的情況去看 VC++ 呢?
: 如果你真的完全不想這種可能性, 應該早就值疑上篇測試的結果作假了..
前面有人留言說愈快的CPU上那overhead應該愈低,我說在單純只是時脈提升的情形下,
因為要跑的CPU指令數沒變,總cycle數也不會因為CPU用比較快的clock跑就會減少,
那overhead percentagle還是沒變-本來是5%的就還是5%,本來是30%的就還是30%,
除非JIT的最佳化做得更好,減少產生出來的指令數,用跑更快的指令排列去應用CPU的
管線最佳化,不然在單純CPU時脈提升的情形下,這些overhead的比例根本不會降,只會
讓實質的絕對差距愈拉愈大-直接編譯成原生碼的軟體可以利用這愈拉愈大的差距來做
更多事。
表面上,你看到VM跑的code與編譯為原生碼程式間的執行時間差隨著機器變快而減少,
可是能處理的工作量的增長是如何呢?
為了方便計算,假設本來VM生出來的code跑一圈要2M cycle,編譯成原生碼跑一圈只要
1M cycle。在100MHz的CPU上執行時間比會是兩秒比一秒,在200MHz的CPU上會變成一秒
比半秒。你可以說,使用VM的語言與原生碼語言間的差距縮小了一倍,從一秒縮成半秒
;我也可以說,可是一樣的code在一秒內能處理的工作量差距拉大了,從本來的0.5件
比一件,變成一件比兩件,中間差距從0.5拉大到1。當CPU clock拉高到1GHz,這一秒內
可完成工作量的差距已經從100MHz時的0.5件工作拉大到1GHz的5件,中間差4.5件工作。
如果18個月後CPU時脈提高成2GHz,兩份code每秒完成工作量的差距會拉大到10件。
因為現實上看起來差距好像沒那麼大,所以對VM有著美夢的人還在繼續作夢。
5%的差距看起來好像沒什麼,可是已經足夠原生碼的新版程式多做一堆小動作了。
當這差距拉大到10%、20%、30%,又是個什麼樣的境地?你以為VM慢的真的只在IO與GC?
iOS device用的CPU現在確實是還不太快,Android device用的CPU也沒比較好到哪去。
以後CPU clock會繼續往上拉,也許VM派的人會想:這中間時間差距不是縮小了嗎?
可是當我們回到現實看單位時間內能做的事情,原生碼能負擔的工作量成長比VM能做
的工作量成長要快,所以在許多小地方可以提供更好的表現。
那考慮CPU架構改善的場合,情形又是如何?
如果JIT沒與時俱進的配合CPU的改良來生出最佳化的code,根本享受不到這方面的好處。
C/C++編譯器都得改版來加入配合新CPU特性的最佳化功能了。
大家一樣是用ARM based CPU,各家做CPU的巧妙各有不同,Java JIT真能對各家ARM
based CPU應用各CPU獨家的最佳化技巧?指令怎麼排列的執行速度都有差了,還要一家
一種排法,慢慢等比較快。
.NET起碼還可以在安裝時先把IL code executable編譯一遍存一份native code image,
離線的最佳化可以做更多事,Windows on ARM也大可真的配合各家CPU來做這種時候的
最佳化。Java哪時候要照著玩這招?
要不要把GPU與其他平行處理單元再考慮進來?
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 114.32.10.18