Java的性能有某種黑魔法之稱。部分原因在于Java平臺非常復雜,很多情況下問題難以定位。然而在歷史上還有一種趨勢,人們靠智慧和經驗來研究Java性能,而不是靠應用統計和實證推理。在這篇文章中,我希望拆穿一些最荒謬的技術神話。
1.Java很慢
關于Java的性能有很多謬論,這一條是最過時的,可能也是最為明顯的。
確實,在上世紀90年代和本世紀初處,Java有時是很慢。
相關廠商內容
JavaOne 2013再次回歸,7月22-25日上海世博中心,精彩繼續,5月31日前購票享半價!
2013年Esri空間信息技術開發者大會
GIS系列白皮書下載:云GIS平臺介紹——ArcGIS Online
還記得Delphi么?Embarcadero攜ER/Studio、RAD Studio XE和HTML5 Builder重裝上陣
百度技術沙龍第三十八期:個性化推薦(2013年5月25日 周六)
然而從那以后,虛擬機和JIT技術已經有了十多年的改進,Java的整體性能現在已經非常好了。
在6個獨立的Web性能基準測試中,Java框架在24項測試中有22項位列前四。
盡管JVM利用性能剖析僅優化常用的代碼路徑,但這種優化效果很明顯。很多情況下,JIT編譯的Java代碼和C++一樣快,而且這樣的情況越來越多了。
盡管如此,依然有人認為Java平臺很慢,這或許源自體驗過Java平臺早期版本的人的歷史偏見。
在下結論之前,我們建議保持客觀的態度,并且評估一下最新的性能結果。
2.可以孤立地看待單行Java代碼
考慮下面這行短小的代碼:
MyObject obj = new MyObject();
對Java開發者而言,看似很明顯,這行代碼一定會分配一個對象并調用適當的構造器。
我們也許可以據此推出性能邊界了。我們認為這行代碼一定會導致執行一定量的工作,基于這種推定,就可以嘗試計算其性能影響了。
其實這種認識是錯誤的,它讓我們先入為主地認為,不管什么工作,在任何情況下都會進行。
事實上,javac和JIT編譯器都能夠將死代碼優化掉。就JIT編譯器而言,基于性能剖析數據,甚至可以通過預測將代碼優化掉。在這樣的情況下,這行代碼根本不會運行,所以不會影響性能。
此外,在某些JVM中——比如JRockit——JIT編譯器甚至可以將對象上的操作分解,這樣即便代碼路徑還有效,分配操作也可以避免。
這里的寓意是,在處理Java性能問題時,上下文非常重要,過早的優化有可能產生違反直覺的結果。所以最好不好過早優化。相反,應該總是構建代碼,并且使用性能調校技術來定位性能熱點,然后加以改進。
3.微基準測試和你想象的一樣
正如我們上面看到的那樣,檢查一小段代碼不如分析應用的整體性能來的準確。
盡管如此,開發者還是喜歡編寫微基準測試。似乎對平臺底層的某些方面進行修修補補會帶來無窮的樂趣。
理查德·費曼曾經說過:“不要欺騙自己,你自己正是最容易被欺騙的人。”這句話用來說明編寫Java微基準測試這件事是再合適不過了。
編寫良好的微基準測試極其困難。Java平臺非常復雜,而且很多微基準測試只能用于測量瞬時效應,或是Java平臺的其他意想不到的方面。
例如,如果沒有經驗,編寫的微基準測試往往就是測一下時間或垃圾收集,卻沒有抓住真正的影響因素。
只有那些有實際需求的開發者和開發團隊才應該編寫微基準測試。這些基準測試應該完全公開(包括源代碼),而且是可以復現的,還應接受同行評審及進一步的審查。
Java平臺的很多優化表明統計運行和單次運行對結果影響很大。要得到真實可靠的答案,應該將一個單獨的基準測試運行多次,然后把結果匯總到一起。
如果讀者感覺有必要編寫微基準測試,Georges、Buytaert和Eeckhout等人的論文《利用嚴格的統計方法評測Java 性能(Statistically Rigorous Java Performance Evaluation)》是個不錯的開始。缺乏適當的統計分析,我們很容易被誤導。
有很多開發好的工具以及圍繞這些工具的社區(比如Google的Caliper)。如果確實有必要編寫微基準測試,那也不要自己編寫,這時需要的是同行的意見和經驗。
4.算法慢是性能問題的最常見原因
在開發者之間有一個很常見的認知錯誤(普通大眾也是如此),即認為系統中他們控制的那部分很重要。
在探討Java性能時,這種認知錯誤也有所體現:Java開發者認為算法的質量是性能問題的主要原因。開發者考慮的是代碼,因此他們自然會偏向于考慮自己的算法。
實際上在處理一系列現實中的性能問題時,人們發現算法設計是根本問題的幾率不足10%。
相反,與算法相比,垃圾收集、數據庫訪問和配置錯誤導致應用程序緩慢的可能性更大。
大部分應用處理的數據量相對較小,因此,即使主要算法效率不高,通常也不會導致嚴重的性能問題??梢钥隙?,我們的算法不是最優的;盡管如此,算法帶來的性能問題還是算小的,更多性能問題是應用棧的其他部分導致的。
因此我們的最佳建議是,使用實際生產數據來揭開性能問題的真正原因。要測量性能數據,而不是憑空猜測!
5.緩存可以解決所有問題
“計算機科學中的所有問題都可以通過引入一個中間層來解決。”
David Wheeler的這句程序員格言(在互聯網上,這句話至少還被認為是其他兩位計算機科學家說的)非常常見,尤其是在Web開發者之中很流行。
如果未能透徹理解現有的架構,而且分析也已停頓,往往就是“緩存可以解決所有問題”這種謬論抬頭的時候了。
在開發者看來,與其處理嚇人的現有系統,還不如在前面加一層緩存,將現有系統隱藏起來,以此期待最好的情況。無疑,這種方式只是讓整體架構更復雜了,當下一個接手的開發者打算了解系統現狀時,情況會更糟糕。
規模龐大、設計拙劣的系統往往缺乏整體的設計,是一次一行代碼、一個子系統這樣寫出來的。然而很多情況下,簡化并重構架構會帶來更好的性能,而且幾乎總是更容易讓人理解。
原文轉自:http://www.infoq.com/cn/articles/9_Fallacies_Java_Performance