多線程網路編程中如何合理地選擇線程數?


需要的線程數 = qps * latency(單位秒)。 依據是little"s law,類似的應用是tcp中的bandwidth-delay product。如果這個數目遠大於核心數量,應該考慮用非同步介面。

舉例:

  • qps = 2000,latency = 10ms,計算結果 = 2000 * 0.01s = 20。和常見核數在同一個數量級,用同步。

  • qps = 100, latency = 5s, 計算結果 = 100 * 5s = 500。和常見核數不在同一個數量級,用非同步。
  • qps = 500, latency = 100ms,計算結果 = 500 * 0.1s = 50。和常見核數在同一個數量級,可用同步。如果未來延時繼續增長,考慮非同步。


你用Boost的話,

#include &
unsigned concurentThreadsSupported = boost::thread::hardware_concurrency();

可以得到硬體線程數。有幾個硬體線程,你就開幾個軟體線程好了。

當然,你要保證這些線程,全都不調用阻塞的API。如果有阻塞,有等待,比如要做輸出的話,多開幾個線程,可能更合適。

在所有線程都不阻塞的情況下,超出硬體線程數的軟體線程,或者得不到執行的機會,也就沒有意義;或者,更糟糕的,被操作系統調度來調度去,白白帶來線程切換的開銷……


其實一般要看業務的,像我比較了解的網遊業務中,內網伺服器之間的通訊,一個線程足矣,網關的話,需要的就比較多,最多跟cpu核數相等即可


更多的線程,意味著你的代碼就有更多的搶佔cpu的機會,但不一定代表著性能的提高。

所有的程序員之所以了創建了線程都是被逼無奈的選擇。誰都希望通過單線程解決問題,但世界總不是這麼完美的。


《Linux 多線程服務端編程》第80頁。


理想情況下線程數就是你的邏輯內核數量-1。

實際情況不可能那麼理想(每個線程都無阻塞的瘋狂跑)。這就需要你測試了,也許是10倍邏輯內核數,或者50倍都沒準,但不會太高,線程切換也需要開銷。

但是最關鍵的是,你要選線程數肯定是為了性能優化,那麼首先,你要找bottleneck,就好比一個木桶盛水量是由最短那個板決定的。

假如找不到最短那塊木板,錯搞其它木板,搞得再高也沒一點用,白費力氣。

假若把所有木板都搞一遍,浪費時間, 事倍功半 。

假若每次都找准最短木板,則 事半功倍 。


按照常見程度~~ 三種情況吧~~

a. 假設最終cpu計算是瓶頸的話【大多數是這樣】,在處理流程固定的情況下,要看每個request中純cpu計算/整個request處理時間,假設是10%【90%時間阻塞住在io,網路等待~~】, 那差不多 16核 * 10~ 這種多線程或者多進程模式,需要考慮到系統級的線程切換所帶來的性能開銷~~~

b. 如果整個request都使用了非阻塞方式處理,那核心個線程ok啦~

c. 如果cpu不是瓶頸~~那麼~~ 內存~~ 網卡~~ IO~~這幾種資源就是木桶,在滿足資源的情況下,達到最大的吞吐和可以接受的rt~~ 就是目標了吧~~


推薦閱讀:

補碼10000000為什麼可以表示-128?
造輪子厲害是一種什麼樣的體驗?
怎樣才算有資格寫技術博客分享?
大家對 Windows Phone 系統的發展怎麼看?
Python3零基礎自學方法?

TAG:編程 | C | 網路編程 | 多線程編程 |