2012-08-09 116 views
0

我目前正在研究分佈式應用程序的性能。我的目標是一個網絡組件。目前,對於每個連接,都有一個專用的線程在阻塞模式下處理套接字。我的目標是減少線程數量(不會降低性能),並在可能的情況下提高性能。Java中的高優先級線程

我重新設計了網絡組件以使用異步通信,並試圖使用1到2個線程進行整個網絡處理。我做了一個簡單的測試,我在一個循環中寫了一個節點並在另一個節點上讀取,這是爲了測試max nw線程能力,並且我發現我的繁忙循環實現消耗了100%cpu,並且每秒獲得更多操作,要求。所以我在現有的應用程序中集成了這個繁忙循環實現。

問題我發現其他線程不允許這些異步nw線程獲得完整的CPU,即使我有一個8核心系統,我們沒有使用超過400%的cpu。基本上是一個C程序員,我可以通過將我的nw線程綁定到核心並提高其調度優先級來解決此問題,以便其他線程仍可以在其他核心上運行。我無法在Java中做類似的工作。有關Java線程優先級的評論有衝突。另外我不想減少其他線程的優先級,因爲它可能有其自身的副作用。

你會如何解決這個問題?

+0

[看這篇文章](http://stackoverflow.com/questions/2238272/java-thread-affinity),這是關於一種設置線程的處理器親和力,當你使用Java,雖然它是真的使用JNI來完成這項工作。 – 2012-08-09 17:30:02

+0

您希望有兩個線程處理所有網絡流量。至多會使用100%的兩個內核。你在100%運行四個內核,所以從這裏的信息看,你可能沒有問題。是什麼讓你覺得你有問題? – 2012-08-09 17:49:20

+0

抱歉不明確。新流量目前由8個線程處理,並且它們不會消耗超過100%的cpu。 400%是整個應用程序負載。我想通過使用單個(或2個)異步nw線程來減少線程數量。 – user1588261 2012-08-09 17:59:28

回答

3

我有一個庫在Linux和Windows上支持Java中的線程關聯。 https://github.com/peter-lawrey/Java-Thread-Affinity

如果隔離CPU,則可以確保您分配的CPU不會用於其他任何內容(非屏蔽中斷除外)這在Linux AFAIK中效果最佳。


如果您使用非阻塞NIO忙於等待阻塞IO,則可以獲得較低延遲結果。後者在負載下工作得最好,在較低負載下延遲可以增加。

你可能會發現這個庫很有趣https://github.com/peter-lawrey/Java-Chronicle它允許你每秒鐘持有數百萬條消息,可選擇到第二個進程。

BTW:線程優先級只是一個暗示,該操作系統是免費的忽略它(常常)


一個簡單的例子VS冷碼比較溫暖。它所做的只是重複複製一個數組並重新定時。一旦代碼和數據變暖,你不會期望它會變慢,但所需要的只是一個10毫秒的延遲,即使是在一臺相當的機器上,也可以顯着減緩複製所需的時間。

public static void main(String... args) throws InterruptedException { 
    int[] from = new int[60000], to = new int[60000]; 
    for (int i = 0; i < 10; i++) 
     copy(from, to); // warm up 
    for (int i = 0; i < 10; i++) { 
     long start = System.nanoTime(); 
     copy(from, to); 
     long time = System.nanoTime() - start; 
     System.out.printf("Warm copy %,d us%n", time/1000); 
    } 
    for (int i = 0; i < 10; i++) { 
     Thread.sleep(10); 
     long start = System.nanoTime(); 
     copy(from, to); 
     long time = System.nanoTime() - start; 
     System.out.printf("Cold copy %,d us%n", time/1000); 
    } 
} 

private static void copy(int[] a, int[] b) { 
    for (int i = 0, len = a.length; i < len; i++) 
     b[i] = a[i]; 
} 

打印

Warm copy 20 us 
Warm copy 20 us 
Warm copy 19 us 
Warm copy 23 us 
Warm copy 20 us 
Warm copy 20 us 
Cold copy 100 us 
Cold copy 80 us 
Cold copy 89 us 
Cold copy 92 us 
Cold copy 80 us 
Cold copy 112 us 
+0

我可以問一下嗎?所以有一種方式,用Java來分配一個CPU來完成你的工作? – Eugene 2012-08-09 18:12:28

+0

在Linux上,您可以告訴操作系統不要在CPU上安排任何事情,然後您可以爲該CPU分配特定的線程(或進程)。它是間接的,但它的工作原理非常好。我對Windows或MAC操作系統沒有相同的控制 – 2012-08-09 18:30:42

+0

這是驚人的,我不知道這個,所以很想測試你寫的庫。謝謝! – Eugene 2012-08-09 18:32:49

1

這真的嫌過早優化的給我。你有一個8核心系統,只使用400%的CPU。是什麼讓你認爲這不是IO界限程序的教科書範例?是什麼讓你覺得你還沒有完成你的網絡IO鏈?

@Peter知道他的東西,我確信你可以破解處理器的親和力,並強制你的關鍵線程到一個單一的CPU,但問題是它會讓你的程序運行得更快嗎?我真誠地懷疑它。模型Java虛擬機是聰明的線程調度,我建議它正在適當地做它的工作。除非你有相反的證據,否則我會讓它處理日程安排。如果大多數線程正在等待IO,則優先級意味着很少。

另外,是什麼讓你覺得減少線程數是多少更好。這將很多來自本地的代碼(即線程多路複用)移動到Java域(即NIO代碼)。如果你正在談論1000線程,那麼我會同意,但即使是100線程也應該是處理連接的有效方法。

我已經完成了超過二十年的大量線程編程,並且我從來不必強制線程關聯。當然,確定線程池的大小並就如何應用線程池與專用線程做出正確的決定是一種藝術,但強制VM按照您認爲應該的方式安排線程並不能很好地利用您的時間。花一些時間與一個探查器找出你的程序花費的時間將是一個更好的投資恕我直言。

+0

在我的實驗中,我只有1個異步網絡線程正在遍歷所有端點。我期待這個線程將抓住100%的CPU。當我在isoloation中運行此測試時,情況正是如此,但是當我打開其他功能並因此啓用更多線程時,情況有很大不同。看來linux調度程序不允許將該線程調度爲100%,即使在8核心系統負載不超過400%的情況下也是如此。 – user1588261 2012-08-10 05:09:31

+0

你正在做所有終點的繁忙循環?哇。看起來像一個真正可疑的架構。每個終點的線程真的不成立?有多少個終點?如果你不使用NIO來替換每個線程的終點,那麼我不能相信你的方式更好。但很難知道@ user1588261而不知道細節。 – Gray 2012-08-10 14:07:50

相關問題