原文:https://chanjarster.github.io...html
如今有一个task,它的执行时间分为2部分,第一部分作数学运算,第二部分等待IO。这两部分就是所谓的计算操做与等待操做。git
那么如今要求估算在CPU火力全开的状况下,执行这个task可以达到的吞吐量峰值是多少?github
那么咱们要先知道执行这个task总共须要多少时间,计算部分花费多少时间,等待部分花费多少时间。ide
假设这个task的计算部分花费1秒,等待部分花费9秒,而且开了10个线程执行10个task,在单核CPU的状况下能够获得下面的执行图:post
图中的蓝色线条是等待调度,橙色线条是执行计算任务,绿色线条是CPU等待花费的时间。性能
能够得益于开了10个线程,每一个task能够利用其余task的等待时间里执行本身的计算操做,同时使得CPU始终处于忙碌状态,即利用率100%。这也告诉你,就算你开11个线程也不会获得更多好处。spa
上面这个图的计算任务是按顺序执行的,这只是一个假想状况,实际中操做系统会将这10个线程交替运行,见图中的红色线,操做系统能够在这个范围内对这10个task的计算任务作任意调度。若是去除线程调度的开销,花费的总时间其实仍是等于10秒的。操作系统
这个图的吞吐量就显而易见了:线程
throughput = 10 tasks / (10 * computing time + wait time) = 10 tasks / (10 * 1s + 9s) = 10 / 19s = 0.526 tasks/s
若是咱们如今有一个双核CPU,那么会怎样呢?3d
能够看到由于有了2个CPU核心,计算任务能够重叠,进而花费的时间减半,吞吐量为:
throughput = 10 tasks / (10 * computing time / 2 + wait time) = 10 tasks / (10 * 1s / 2 + 9s) = 10 / 14s = 0.7142 tasks/s
那么总结一下吞吐量计算公式:
公式中C=1的意思是CPU 100%的全速工做,若是C=0.5那么意思就是CPU有50%的空闲时间,若是C=2则表明启动了两颗CPU全速运行。
能够看到想要提高吞吐量有:
总的来讲就是使用更多的CPU核,让task运行时间更短。
也许你以为还能够经过提高Tn来提升吞吐量,好比下面这个图:
能够看到吞吐量随着任务数量的上升而上升,那么是否是会一直长呢?答案是不会的,当Tn愈来愈大的时候,Tn * Tc / C 也会愈来愈大,那么能够忽略掉Tw,公式就变成了 C / Tc,这值就是理论上的吞吐量上界,增长Tn只会无限趋近于这个值。
那么问题来了,如何知道要开多少个线程可以让CPU达到目标利用率?
这个要看下面的公式:
注:本公式里的 N * U = 吞吐量公式中的C。
若是U=1(利用率100%),决定线程数量的是W与C的比,当W越高时则须要越多的线程,当W=0时,只须要与N一样的线程便可。
这个公式也告诉咱们开启更多的线程不会带来额外的好处,还会形成反效果(增长的线程调度开销),因此在实践中都会使用具备上界的线程池。
并且在实际作性能调优的时候,会在计算获得的数字左右调整线程池大小,以达到最好效果。