我们正在编写一个应该处理大量流量的前端(在我们的例子中,它是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进行。
答案 0 :(得分:3)
如果工作人员使用的程序代码的大小或工作人员(或两者)处理的数据大小都不小,那么的原因可能是各种缓存的效率降低:单个工作人员如何访问其程序代码和/或其数据的位置随着时间的推移而被其他工作人员介入干扰。
理解效果可能非常复杂,因为:
但是那么:你有没有看过“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的文章,您可以阅读它以获取更多详细信息。