Sun公司的Kohsuke Kawaguchi考察了Hotspot JIT在JDK6 u10 b14 debug版中產生的匯編代碼,并將其記錄在博客中。該博文著重闡述了Java優化的程度。
Kawaguchi 將重點放在兩個主要的地方。首先是循環展開(loop unrolling),它是這樣一種技術:復制循環的每次迭代所調用的指令以構成一個序列。通過減少循環中計算機需要執行的指令,節省了執行時間。JIT 將其與預處理和事后分析相結合,同時Kawaguchi對此的補充也說明了這樣的事實:編譯器已從循環的快速執行部分當中移除了一個冗余的數組索引檢查。此外,結果匯編代碼證明了特定于處理器的優化程度如何。例如,Kawaguchi談到了下面的代碼:
private static byte[] foo() { byte[] buf = new byte[256]; for( int i=0; i buf[i] = 0; return buf; }
所產生的匯編結果使用了特定于AMD64芯片的R8-R15通用寄存器匯編代碼。
其次是圍繞著鎖(locks)而進行的優化。在Java中非競態鎖的獲取在不斷地改進,而競態鎖的獲取卻一直存在問題。這個領域的工作還在持續進行中,但是Kawaguchi的工作卻說明了幾個已經得到改進的地方。
這篇文章展示了該Hotspot編譯器很多其他的特性,包括強大的內聯——James Gosling注意到一篇相關的博文中說“甚至連存儲分配和初始化都需要內聯”。這一層級的侵略性(aggression)是可能存在的,部分原因在于 JVM會在必要時做一些潛在不安全的優化。Charles Nutter在今年初參加Lang.NET大會時曾對此提出了一個很好的解釋。他也強調了這項工作與JRuby的關系,以及與任何面向JVM的語言的關系。
“過去JVM有多種不同的能力去動態優化和再優化代碼……或許最重要的是必要時的動態“逆優化(deoptimize)”。在處理性能問題時,逆優化(Deoptimization)令人非常興奮,因為這意味著你可以進行更多的侵略性優化——對整個應用不確定的未來的潛在的不安全的優化——知道你可以在安全的路徑上回退。一旦你幾次遇到相同的路徑,你就可以內聯整個調用路徑。除非明顯需要,你可以忽略同步保護。你還可以在發現問題之后改變使用的優化集……本質上,在運行過程中你可以安全的“出錯”并且從錯誤中學習。這就是為什么在特定的基準上Java超越了C和C++以及最終在幾乎所有基準上它都能將超越C和C++的主要原因。同時這也是我們的JRuby與微軟的IronPython和DLR相比,只需要做很少的事情就可以獲得可接受的性能的一個關鍵原因。”
從理論上講,像Java這樣的解釋型語言的性能很有可能最終將超越編譯型語言,因為它可以在運行時基于現有硬件進行優化,同時Java中不斷提高的對特定于處理器的優化確實令人非常興奮。對于面向Java平臺的開發者來說,一個額外的好處在于隨著新版本 Java編譯器的發布,代碼的性能會不斷改進,而無需對應用的源碼做任何更改。
英文原文:
http://www.infoq.com/news/2008/05/hotspot_performance
新浪微博:http://t.sina.com.cn/androidguy 昵稱:李寧_Lining