整理:如何估算吞吐量以及線程池大小

原文:https://chanjarster.github.io...

估算吞吐量

現在有一個task,它的執行時間分爲2部分,第一部分做數學運算,第二部分等待IO。這兩部分就是所謂的計算操作與等待操作。

那麼現在要求估算在CPU火力全開的情況下,執行這個task能夠達到的吞吐量峯值是多少?

那麼我們要先知道執行這個task總共需要多少時間,計算部分花費多少時間,等待部分花費多少時間。

假設這個task的計算部分花費1秒,等待部分花費9秒,並且開了10個線程執行10個task,在單核CPU的情況下可以得到下面的執行圖:

圖中的藍色線條是等待調度橙色線條執行計算任務綠色線條CPU等待花費的時間。

可以得益於開了10個線程,每個task可以利用其他task的等待時間裏執行自己的計算操作,同時使得CPU始終處於忙碌狀態,即利用率100%。這也告訴你,就算你開11個線程也不會得到更多好處。

上面這個圖的計算任務是按順序執行的,這只是一個假想情況,實際中操作系統會將這10個線程交替運行,見圖中的紅色線,操作系統可以在這個範圍內對這10個task的計算任務做任意調度。如果去除線程調度的開銷,花費的總時間其實還是等於10秒的。

這個圖的吞吐量就顯而易見了:

throughput = 10 tasks / (10 * computing time + wait time) 
           = 10 tasks / (10 * 1s + 9s) 
           = 10 / 19s = 0.526 tasks/s

如果我們現在有一個雙核CPU,那麼會怎樣呢?

可以看到因爲有了2個CPU核心,計算任務可以重疊,進而花費的時間減半,吞吐量爲:

throughput = 10 tasks / (10 * computing time / 2 + wait time) 
           = 10 tasks / (10 * 1s / 2 + 9s) 
           = 10 / 14s = 0.7142 tasks/s

那麼總結一下吞吐量計算公式:

  • Throughput:吞吐量。
  • Tn(task-n):task數量。
  • C:CPU數量。可以有小數,比如0.5,代表只提供一半的算力。
  • Tc(task-computing):task計算所花費的時間。
  • Tw(task-wait):task等待花費的時間。
  • E(end):最後一個task完成所消耗的時間。(或者使用平均響應時間)

公式中C=1的意思是CPU 100%的全速工作,如果C=0.5那麼意思就是CPU有50%的空閒時間,如果C=2則代表啓動了兩顆CPU全速運行。

可以看到想要提升吞吐量有:

  • 提高C,這個下面會講。
  • 降低Tc
  • 降低Tw

總的來說就是使用更多的CPU核,讓task運行時間更短。

也許你覺得還可以通過提升Tn來提高吞吐量,比如下面這個圖:

可以看到吞吐量隨着任務數量的上升而上升,但是不會一直長的,超過最大併發任務數,會導致CPU線程切換頻繁,內存佔用,從而導致,響應時間增加,吞吐量下降。

估算線程池大小

那麼問題來了,如何知道要開多少個線程能夠讓CPU達到目標利用率?

簡單來說:

cpu_count * (1+ average_wait_time/average_run_time)

線程池核心線程數 = CPU個數*(1+平均等待時間/平均運行時間)

這個要看下面的公式:

  • N:CPU數量。
  • U:CPU利用率,0.1代表10%,1代表100%。
  • C:用到CPU的時間。
  • W:等待時間。

注:本公式裏的 N * U = 吞吐量公式中的C。

如果U=1(利用率100%),決定線程數量的是W與C的比,當W越高時則需要越多的線程,當W=0時,只需要與N同樣的線程即可。

這個公式也告訴我們開啓更多的線程不會帶來額外的好處,還會造成反效果(增加的線程調度開銷),所以在實踐中都會使用具有上界的線程池。

而且在實際做性能調優的時候,會在計算得到的數字左右調整線程池大小,以達到最好效果。

參考資料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章