【发布时间】:2015-09-21 15:46:57
【问题描述】:
我们遇到了一个奇怪的现象,其中包含头文件会导致某些内存分配密集型工作负载的性能下降 5-10%。
此头文件将线程池声明为全局变量。此线程池从未在应用程序中以任何容量(尚未)使用。也就是说,除了在程序启动时创建这个静态线程池之外,应用程序完全是单线程的。删除标头后,性能损失就消失了。
通过一些研究,由于某些编译器优化不再可能,多线程应用程序似乎会导致一些性能损失。每当以任何形式或容量实例化与线程相关的构造时,是否有可能关闭此类优化?
或者,由于在执行大量内存分配时性能损失似乎最为明显,在编译/链接阶段编译器是否可能意识到线程构造已被实例化,因此它切换到线程安全的内存分配器?
这发生在带有 GCC 和 clang 的 Linux 64 位工作站上。正在使用来自 C++11 的标准线程原语。
编辑我还应该提到,根据我们的测试,当使用 tcmalloc 分配器而不是默认分配器时,性能差异似乎消失了。
【问题讨论】:
-
这真的很吸引人。您是否可以发布一个最小的可编译示例来演示该现象?
-
除了添加的变量之外,目标文件是否发生了变化?
-
这种“在程序启动时创建静态线程池”是否涉及主线程和/或工作线程中的任何内存分配?
-
您在不支持的情况下做了一些假设。然而,在 Linux 上,有一个工具可以测量性能并找到争用点。它是
perf(perf.wiki.kernel.org/index.php/Main_Page)。您需要使用它并准确找出问题的根源(而不是猜测)。 brendangregg.com/linuxperf.html 是一个关于性能调优的知名博客。作为提示:perf record- 使用 CPU 周期记录应用程序性能(对于 CPU 密集型应用程序),perf record -F 99记录应用程序性能以找到争用点。 -
如果优化被关闭,那么你应该能够在区分
objdump -d的输出时看到这一点。否则……那些线程“活着”吗?那么原因可能是操作系统给了他们时间片,尽管这表明线程设施的实现很不幸。
标签: c++ multithreading c++11