CPU负载不能与流量处理工作者的数量成线性关系的原因是什么?

时间:2015-01-16 14:36:34

标签: performance performance-testing

我们正在编写一个应该处理大量流量的前端(在我们的例子中,它是Diameter流量,但这可能与问题无关)。当客户端连接时,服务器套接字被分配给执行所有实际流量处理的Worker进程之一。换句话说,工作人员完成所有工作,当更多客户连接时,应添加更多工人。

可以预期,对于不同数量的Workers,每条消息的CPU负载是相同的,因为Workers完全独立,并提供不同的客户端连接集。然而,我们的测试表明,随着工人数量的增长,每条消息需要更多的CPU时间。

更准确地说,CPU负载取决于TPS(每秒事务或请求响应),如下所示。

对于1名工人: 60K TPS - 16%,65K TPS - 17%......即每KTPS的CPU为0.26%

2名工人: 80K TPS - 29%,85K TPS - 30%......即每KTPS的CPU为0.35%

4名工人: 85K TPS - 33%,90K TPS - 37%......即每KTPS CPU约0.41%

对此有何解释?工人是独立的流程,他们之间没有进程间的沟通。此外,每个Worker都是单线程的。

编程语言是C ++ 在任何硬件上都可以观察到这种效果,这个硬件接近这个:2个Intel Xeon CPU,4-6个内核,2-3 GHz 操作系统:RedHat Linux(RHEL)5.8,6.4 CPU负载测量使用mpstat和top进行。

2 个答案:

答案 0 :(得分:3)

如果工作人员使用的程序代码的大小或工作人员(或两者)处理的数据大小都不小,那么的原因可能是各种缓存的效率降低:单个工作人员如何访问其程序代码和/或其数据的位置随着时间的推移而被其他工作人员介入干扰。

理解效果可能非常复杂,因为:

  • 它大大依赖于代码计算的结构,
  • 现代CPU有about three levels of cache
  • 每个缓存都有不同的大小,
  • 某些缓存是一个核心的本地缓存,其他缓存不是,
  • 工人干预的频率取决于您的操作系统的调度策略
  • 如果有多个核心,
  • 会变得更复杂,
  • 除非您的编程语言的运行时系统也介入, 在这种情况下,它仍然更复杂,
  • 您的网络接口本身就是一台计算机,并且还有一个缓存
  • 可能更多。
警告:

但是那么:你有没有看过“CPU的百分比”是如何定义的? 在您的计算机上达到CPU 饱和度之前,您无法确定效果实际上是否与其外观一样大。当你达到饱和状态时,它可能根本就不是CPU的瓶颈,所以你确定你需要关心CPU负载吗?

答案 1 :(得分:1)

我完全赞同@Lutz Prechelt。在这里,我只想添加有关如何调查问题的方法,答案是Perf

Perf是Linux中的一种性能分析工具,它收集内核和用户空间事件并提供一些不错的指标。它被我的团队广泛用于在CPU绑定应用程序中找到底层。

perf的输出是这样的:

 Performance counter stats for './cache_line_test 0 1 2 3':

1288.050638 task-clock                #    3.930 CPUs utilized
        185 context-switches          #    0.144 K/sec
          8 cpu-migrations            #    0.006 K/sec
        395 page-faults               #    0.307 K/sec
3,182,411,312 cycles                    #    2.471 GHz                     [39.95%]
2,720,300,251 stalled-cycles-frontend   #   85.48% frontend cycles idle    [40.28%]
764,587,902 stalled-cycles-backend    #   24.03% backend  cycles idle    [40.43%]
1,040,828,706 instructions              #    0.33  insns per cycle
                                      #    2.61  stalled cycles per insn [51.33%]
130,948,681 branches                  #  101.664 M/sec                   [51.48%]
     20,721 branch-misses             #    0.02% of all branches         [50.65%]
652,263,290 L1-dcache-loads           #  506.396 M/sec                   [51.24%]
 10,055,747 L1-dcache-load-misses     #    1.54% of all L1-dcache hits   [51.24%]
  4,846,815 LLC-loads                 #    3.763 M/sec                   [40.18%]
        301 LLC-load-misses           #    0.01% of all LL-cache hits    [39.58%]

它会输出您的缓存未命中率,您可以轻松调整程序并查看效果。

我写了一篇关于cache line effects and perf的文章,您可以阅读它以获取更多详细信息。