2011-04-19 19 views
8

背景信息維護具有大量線程的Java應用程序時,我需要知道什麼?

我有一個分佈式處理應用程序,可以進行數據分析。它旨在對多組實時更新的數據進行並行處理。作爲設計的一部分,分析已經分解成分析節點。每個節點獲取源數據並對其進行處理以創建其他數據,然後可以由其他節點使用這些數據。爲了對一個數據集進行當前的全套分析,需要大約200個節點。

在當前的設計中,每個節點都使用自己的線程運行。現在,大多數時候這些線程都睡着了。無論什麼時候更新數據,它們都會像瀑布一樣依次喚醒,然後再回到睡眠狀態。該應用程序目前正在生產運行40組數據,每個數據需要200個節點,使用8000個線程。當沒有數據進入時,服務器上沒有負載。當數據在最繁忙時間進入時,服務器峯值約爲CPU的25%。這完全在項目的設計和生產參數範圍內。

現在爲了下一步,我們將40組數據縮放到200.每組需要200個節點,這意味着總共40000個節點,即40000個線程。這超過了我們服務器的最大PID,所以我要求我們的服務器管理員增加上限。他們這樣做了,應用程序可以工作,但是他們給了我一些關於線程數量的推斷。我並不否認線程的數量是不尋常的,但在我們設計的這個階段,這是預期和保證的。

我正在計劃一些小設計來將線程從節點分開。這將允許我們配置一個線程來運行多個節點,並減少線程數量。對於不經常更新的數據集,只有一個線程在每個節點中執行數據更新的性能影響非常小。對於每秒更新數百次的數據集,我們可以將每個節點配置爲在其自己的線程上運行。事實上,我不懷疑這種設計變更將會發生 - 這只是時間問題。同時,我希望儘可能多地瞭解使用此設計的後果。

問題

什麼是與一臺計算機上超過40,000線程中運行的成本呢?讓JVM/Linux操作系統管理這麼多線程會損失多少性能?請記住,在沒有工作的情況下,它們都已正確配置爲可以睡眠。所以,我只是在討論由於線程數量太多而導致的額外開銷和問題。

請注意 - 我知道我可以減少線程的數量,並且我知道這是改變設計的好主意。我會盡快做到,但必須兼顧其他工作和設計考慮。我正在問這個問題來收集信息,以便作出一個好的決定。你對這種性質的想法和評論非常感謝。

回答

9

在一臺機器上運行40,000多個線程的成本是多少?讓JVM/Linux操作系統管理這麼多線程會損失多少性能?請記住,在沒有工作的情況下,它們都已正確配置爲可以睡眠。所以,我只是在討論由於線程數量太多而導致的額外開銷和問題。

在JVM空間中,每個線程都需要一個線程堆棧(默認爲256kb)以及Thread對象和連接的對象。可以使用-Xss選項更改默認線程堆棧,但我相信 64kb是下限。 (40,000 x 256kb是10Gb ...)

在Linux上,每個線程還佔用一個OS線程描述符,這將在線程未執行時幫助線程的註冊上下文...以及其他內容。這些描述符是預先分配的,我相信它們沒有分頁。這是您的管理員需要增加的資源。

無論線程是喚醒還是休眠,都使用這些資源。

另一個問題是,您需要小心使用wait/notifyAll進行同步。如果有很多線程在同一個對象上等待,那麼notifyAll會在每個線程被喚醒時引發一系列的活動。 (但是,您可以通過避免在同一對象上等待很多線程來避免此問題。)

有關使用大量線程的後果的更多信息,請參閱Oracle Java Threading頁面。


我的感覺是40,000個線程過多。理想的線程數與您擁有的物理處理器/內核的數量成正比。雖然你不一定會看到有大量線程的性能下降,但你會佔用很多資源,並且可能會有間接的性能問題;例如更長的GC時間,潛在的VM抖動。

爲您的應用程序提供更好的體系結構將實現線程池和工作隊列,以將工作分配到更少數量的活動線程。

+0

+1,以表示線程過多和使用執行程序服務的好處。 – 2011-04-19 15:42:53

+1

釘牢它。謝謝您的幫助。這不應該是一個難題。現在我明白他們爲什麼說擴展'Thread'是不好的。沒有什麼東西像經驗教訓一樣。 – 2011-04-19 22:38:26

2

現在你說線程在沒有工作時會睡覺。多久工作一次?同時進行多少單位的工作?如果這個數字大於處理器的數量,並且所述的工作主要是基於CPU的,那麼實際上您會看到整體性能下降。

但讓我們假設在任何給定時間完成的工作量是處理器的數量。如果是這樣的話,我能看到的頭號問題是將發生的上下文切換量。 Java中的上下文切換(通常基於)大約有100個工具。如果你所有的線程都在短時間內被喚醒(喚醒)完成一些工作,那麼我們正在討論> 4,000,000個額外的指令。

關於上下文切換成本的更多信息,因爲它們可能會影響您的程序而不是任何事情。從這個document摘錄當一個新的線程切換在

切換時解釋驗證線程的本地緩存的成本,它需要 數據不太可能在 本地處理器高速緩存,所以上下文 交換機導致一系列高速緩存未命中,因此線程在第一個 排定時運行得更慢。這是原因之一 該調度給每個可運行 線程一定的最小時間段 即使許多其​​它線程 等待

除此之外你需要添加的堆棧空間分配,以及有爲40,000個線程對象堆棧(對於線程來說,這只是大約7兆的淺堆)。

+0

好的,所以我可以看到一些優化,如果我要將一些較小的數據集合合併爲一個線程。當它走下分析樹時,它在第一步中生成的數據將被第二步等使用,並且這些數據將更有可能在處理器緩存中四處閒逛。隨着這種分裂,不能保證每個連續的步驟甚至會在同一處理器中被喚醒。這似乎並不是一個足夠嚴重的問題,我們無法在此設計下運行一段時間,直到我們可以安排下一個工作。 – 2011-04-19 14:55:38

相關問題