为什么拥有更多更快的内核会使我的多线程软件变慢?

sor*_*h-r 4 debian kernel threads multi-threading

我在扩展多进程/多线程 C++ 应用程序时遇到奇怪的行为。该应用程序包含 10 个独立的进程,通过Unix 域套接字进行通信,每个进程都有大约 100 个执行 IO 的线程以及该 IO 上的多个进程。该系统是OLTP,事务处理时间至关重要。IPC IO 基于在 unix 域套接字上使用 zmq 的 boost 序列化(在我们的本地服务器(两个具有 24 核的旧 xeon)上的所有基准测试中,它足够快)。现在,我们在具有更多内核的系统上观察到极其低的性能!

\n

1x Intel\xc2\xae Xeon\xc2\xae X5650 - 虚拟 - 6 核 - TPS 约为 150(预期)
\n1x Intel\xc2\xae Xeon\xc2\xae E5-4669 v4 - 专用 - 32 核 - TPS 约为 150(预期) 700(预期)
\n2x Intel\xc2\xae Xeon\xc2\xae E5-2699 v4 - 专用 - 88 个核心 - TPS 约为 90(应该约为 2000)

\n

在第三台服务器上运行多个基准测试显示处理器能力完全正常。内存带宽和延迟看起来正常。

\n

htop 在内核上显示非常高的时间(红色部分)。所以我们的第一个猜测是某些系统调用需要很长时间才能完成,或者我们在多线程代码中做错了什么。(见下图)perf top报告一个特定的系统调用/内核例程 ( native_queued_spin_lock_slowpath) 占用了大约 40% 的内核时间(见下图),但我们不知道它的作用。

\n

然而,另一个非常奇怪的观察是:

\n

减少分配给进程的核心数量,使系统更好地利用核心(更多绿色部件,更高的 CPU 使用率),并使整个软件(所有 10 个进程)运行得更快(TPS 约为 400)。

\n

因此,当我们运行进程时,taskset -cp 0-8 service我们达到了约 400 TPS。

\n

您如何解释为什么将分配的 CPU 数量从 88 个减少到 8 个会使系统运行速度提高 5 倍,但性能仅为 88 核上预期性能的 1/4?

\n

其他信息:
\n操作系统:Debian 9.0 amd64
\n内核:4.9.0

\n

顶级结果\n性能最高结果

\n

Joh*_*ald 5

当多个套接字大幅降低性能时,看起来确实像是 NUMA 效应。

perf非常有用。在性能报告中,您可以看到native_queued_spin_lock_slowpath占用了 35%,这对于并发代码来说似乎是一个非常大的开销。棘手的部分是可视化什么在调用什么,如果您不太了解并发代码。

我建议从系统范围的 CPU 采样中制作火焰图。快速开始:

git clone https://github.com/brendangregg/FlameGraph  # or download it from github
cd FlameGraph
perf record -F 99 -a -g -- sleep 60
perf script | ./stackcollapse-perf.pl > out.perf-folded
./flamegraph.pl out.perf-folded > perf-kernel.svg
Run Code Online (Sandbox Code Playgroud)

在生成的图形中,查找最高的“高原”。表示具有最独占时间的函数。

我期待当该bpfcc-tools软件包在 Debian 稳定版中时,它将能够以更少的开销直接收集这些“折叠”堆栈。

你用它做什么取决于你发现了什么。了解哪个关键部分受到锁的保护。与现代硬件上可扩展同步的现有研究进行比较。例如,并发工具包演示指出不同的自旋锁实现具有不同的属性