2014-02-10 68 views
3

我有一個運行在(大)圖上的Java程序。因此,它使用了大量的堆空間(大約50GB,大約是主機上物理內存的25%)。在某一點上,程序(重複)從圖中選取一個節點並用它進行一些計算。對於某些節點,這種計算花費的時間比預期長得多(30-60分鐘,而不是預計的幾秒鐘)。爲了剖析這些操作以找出花費那麼多時間,我創建了一個測試程序,僅創建大圖的一小部分,然後在需要很長時間計算的節點之一上運行相同的操作原來的程序。因此,與原始程序相比,測試程序顯然只使用非常小的堆空間。Java的大堆比較慢

事實證明,在測試程序中,在原始程序中花了48分鐘的操作可以在9秒內完成。這真讓我困惑。首先想到的可能是較大的程序花費大量的時間進行垃圾回收。所以我打開了虛擬機垃圾收集器的詳細模式。據此,在48分鐘內沒有完整的垃圾收集,而年輕一代只收集約20個垃圾收集,每個垃圾收集少於1秒。

所以我的問題是還有什麼可以解釋這樣一個巨大的時間差異?我不太瞭解Java如何組織堆。有大量實時對象的大堆需要更長的時間嗎?難道在這種環境下對象分配需要更長的時間,因爲在堆中找到足夠的位置需要更長的時間?或者,虛擬機會對堆進行任何內部重組,這可能需要很長時間(顯然,除了垃圾回收之外)。

我正在使用Oracle JDK 1.7,如果這是任何重要的。

+3

不知道你的程序做了什麼樣的操作,這是不可能回答的。 –

+0

測試和主程序還有什麼不同,比可分配堆的數量還多?他們是否使用其他類型的數據?測試應用程序使用了多少堆,如果僅使用小堆,則使用短指針的性能選項(但這無法解釋您的性能差異) – ooxi

+0

您應該使用良好的分析器(例如YourKit)來分析緩慢的原因,我發現很難相信這裏的任何人都能猜出問題的根源。 – alfasin

回答

3

雖然更大的內存可能意味着更大的問題,但我會說沒有任何東西(除了你排除的GC)什麼可以延長9秒到48分鐘(因子320)。

一大堆使得表面上看起來更糟的空間位置成爲可能,但我認爲它不重要。我不同意蒂姆的回答w.r.t. 「必須離開高速緩存的所有內容」。

另外還有TLB這對於虛擬地址轉換,這可能會導致一些問題的非常大的內存高速緩存。但再次,不是因素320.

我不認爲有任何可能導致此類問題的JVM中。

我能想到的唯一原因是你有一些交換空間被使用 - 儘管你有足夠的物理內存。即使輕微的交換也可能導致巨大的放緩。確保它關閉(並可能檢查swappiness)。

+0

據我所知,沒有交換正在發生。根據你的回答,我只能推斷出問題出在我的代碼中。我將不得不進一步調查。謝謝! – Georg

0

即使事情在內存中,您在現代CPU上也有多級緩存數據。每次你離開緩存取數據的速度會變慢。擁有50GB內存可能意味着它不得不離開緩存。

你描述的症狀和差異只是巨大的,但我沒有看到像高速緩存一致性那樣簡單,使差別很大。

我可以給你五個最好的建議就是在運行速度慢,運行速度快並且比較差異時嘗試運行探查器。

您需要堅實的數字和計時。 「在這種環境下,X花費了Y時間」。從這個角度你可以開始縮小範圍。