2011-01-07 92 views
4

我有一種方法,第一次執行需要很多時間。但經過多次調用後,花費的時間減少了大約30倍。所以,爲了讓我的應用程序更快地響應用戶交互,我在初始化應用程序時用一些示例數據「預熱」了此方法(5次)。但是這會增加應用程序的啓動時間。
我讀過,JVM的可以優化和編譯我的Java代碼到本機,從而加快速度。 我想知道 - 也許有一些方法可以明確告訴JVM,我希望在啓動應用程序時編譯此方法?有沒有辦法告訴JVM在處理之前優化我的代碼?

+1

您是否確定它在被完全因爲JVM優化而被調用多次後性能更好。根據你的方法做什麼,它也可能是其他的東西 - 例如,磁盤或數據庫緩存...... – 2011-01-07 14:22:24

+0

@Rogach:你不能先優化你的方法嗎?它做什麼樣的東西? – Gugussee 2011-01-07 14:24:47

+0

這個方法究竟做什麼? – Cratylus 2011-01-07 14:24:57

回答

6

JVM在運行時執行JiT(即時)優化。這意味着它可以分析代碼的執行情況並進行優化以提高運行時性能。這發生在運行時間。如果您看到方法在執行幾次後變得更快,那可能是因爲JiT優化(除非您的分析有缺陷,並且方法因爲數據變得更簡單而變得更快)。如果你的分析是正確的,編譯爲本地可能會傷害你,因爲你將不再獲得運行時優化。

我們可以看到該方法嗎?您可能可以更快地完成工作,而無需擔心JVM的工作方式。您應該隔離確切地說哪裏是最昂貴的操作。您還應該驗證這不是某種垃圾收集問題。也許這種方法很好,但是有一個GC正在咀嚼時間,當它完成時,你的方法以可接受的速度運行。

3

的JIT優化工作這麼好,正是因爲他們優化實際上做什麼你的代碼,而不是它可能在不同的情況下做的。

由於輸入數據不同,甚至有可能JITted代碼在不同的運行中不同。甚至在情況發生變化時甚至可以不止一次地重新優化。

換句話說:沒有真實數據,JVM將無法很好地優化代碼。 (即它只能做「靜態」優化)

但到最後,如果你要這麼高的改進(30X是很多!),它很可能是它要麼

  • 不代碼,但其他東西(如文件或數據庫緩存)
  • 非常在源級別的非最佳代碼。 (像一些重計算,可以去緊密的循環出)

編輯:

看你的代碼,在一個大循環上Literas.prepareLiteras()後,你一直打電話path.contains(p)與不同點,但相同的路徑。 SimplePath.contains()每次調用時會創建一個邊界形狀,因此您最終會一次又一次創建相同的形狀。這是應該從內部循環中撤出的一個主要例子。

我不認爲JIT可以優化整個方法,但在某些極端情況下,它可能會將getShape()轉換爲專用於單個路徑的內容,併爲下一個路徑再次重新編譯。不是很好的使用JVM智能,呃?

2

如果使用Sun JVM,則JIT編譯的閾值有所不同,具體取決於您使用的是客戶端還是服務器JVM。對於客戶端來說,對一個方法來說是1500個調用,對於服務器來說是10000個。你可以使用JVM參數-XX:CompileThreshold=100將其更改爲非常低的值。

儘管如此低的門檻不會有利於您的全球業績。我只建議使用它來測試通過預熱來改善性能是否受到JIT的影響。

我從來沒有看到因預熱而導致係數30的改善,這是由於JIT優化。然而。這總是由於一些緩存。

2

如果您有64位操作系統,則可以嘗試在64位JVM上運行此操作。

在Oracle的實現中有兩個版本的JVM:客戶端VM和服務器VM。在32位Windows上,客戶端VM是默認值。在64位Windows上,服務器虛擬機是默認的。

客戶端和服務器虛擬機之間的區別在於它們如何進行調整:服務器虛擬機比客戶端虛擬機執行更積極的優化(並且在早期完成)。服務器虛擬機爲長時間運行的進程優化了設置。客戶端虛擬機具有針對桌面使用進行了優化的默認設置:預先進行的優化較少,但啓動速度更快。

我在計算密集型程序中遇到了主要的速度差異;與32位JVM相比,這些有時在64位JVM上運行速度快兩倍。

1

大多數情況下,我會同樣使用hvgotcodes,但也有可能這個問題不是JVM優化,但是在通過磁盤獲得的數據的最初幾次運行之後,現在仍在緩存中,或者前幾次仍然是加載和初始化類,但之後,他們都在記憶中。

相關問題