多線程網路編程中如何合理地選擇線程數?
01-05
需要的線程數 = 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零基礎自學方法?