Nthreads=Ncpu*(1+w/c)
IO密集型:如果存在IO,那么肯定w/c>1(阻塞耗時一般是計算耗時的很多倍),但是需要考慮系統內存有限(每開啟一個線程都需要內存空間),這里需要上服務器測試具體多少個線程數適合(CPU占比、線程數、總耗時、內存消耗)。如果不想去測試,保守點取1即,Nthreads=Ncpu*(1+1)=2Ncpu+1。
計算密集型:假設沒有等待w=0,則W/C=0. Nthreads=Ncpu+1。在擁有N個處理器的系統上,當線程池的大小為N+1時,通常能實現最優的效率。(即使當計算密集型的線程偶爾由於缺失故障或者其他原因而暫停時,這個額外的線程也能確保CPU的時鍾周期不會被浪費。)
如果一台服務器上只部署這一個應用並且只有這一個線程池,那么這種估算或許合理,具體還需自行測試驗證。
服務器性能IO優化 中發現一個估算公式
|
最佳線程數目 = ((線程等待時間+線程CPU時間)/線程CPU時間 )* CPU數目 |
比如平均每個線程CPU運行時間為0.5s,而線程等待時間(非CPU運行時間,比如IO)為1.5s,CPU核心數為8,那么根據上面這個公式估算得到:((0.5+1.5)/0.5)*8=32。這個公式進一步轉化為:
|
最佳線程數目 = (線程等待時間與線程CPU時間之比 + 1)* CPU數目 |
可以得出一個結論:
線程等待時間所占比例越高,需要越多線程。線程CPU時間所占比例越高,需要越少線程
一個系統最快的部分是CPU,決定一個系統吞吐量上限的是CPU。增強CPU處理能力,可以提高系統吞吐量上限。但根據短板效應,真實的系統吞吐量並不能單純根據CPU來計算。那要提高系統吞吐量,就需要從“系統短板”(比如網絡延遲、IO)着手:
- 盡量提高短板操作的並行化比率,比如多線程下載技術
- 增強短板能力,比如用NIO替代IO
第一條可以聯系到Amdahl定律,這條定律定義串行系統並行化后的加速比計算公式:
|
加速比=優化前系統耗時 / 優化后系統耗時 |
加速比越大,表明系統並行化的優化效果越好。Addahl定律還給出系統並行度、CPU數目和加速比的關系,加速比為Speedup,系統串行化比率(指串行執行代碼所占比率)為F,CPU數目為N:
|
Speedup <= 1 / (F + (1-F)/N) |
當N足夠大時,串行化比率F越小,加速比Speedup越大。
是否使用線程池就一定比使用單線程高效呢?
答案是否定的,比如Redis就是單線程的,但它卻非常高效,基本操作都能達到十萬量級/s。從線程這個角度來看,部分原因在於:
- 多線程帶來線程上下文切換開銷,單線程就沒有這種開銷
- 鎖
當然“Redis很快”本質的原因在於:Redis基本都是內存操作,這種情況下單線程可以很高效地利用CPU。而多線程適用場景一般是:存在相當比例的IO和網絡操作。
所以即使有上面的簡單估算方法,也許看似合理,但實際上也未必合理,需要結合系統真實情況(比如是IO密集型或者是CPU密集型或者是純內存操作)和硬件環境(CPU、內存、硬盤讀寫速度、網絡狀況等)來不斷嘗試達到一個符合實際的合理估算值。
參考:
http://ifeve.com/how-to-calculate-threadpool-size/
