查找可能由线程锁定引起的性能问题(可能)

Posted

技术标签:

【中文标题】查找可能由线程锁定引起的性能问题(可能)【英文标题】:Finding performance issue that may be due to thread locking (possibly) 【发布时间】:2014-06-03 18:01:53 【问题描述】:

我花了一点时间运行 valgrind/callgrind 来分析使用许多线程进行大量 TCP/IP 通信的服务器。经过一段时间的性能提升后,我意识到在这个特定的测试场景中,进程不受 CPU 限制,因此我所看到的性能“提升”毫无用处。

理论上,CPU 应该很忙。我知道它连接的 TCP/IP 设备不是限制,因为服务器在两台机器上运行。一个是 PC,另一个是带有 Arm 处理器的嵌入式设备。即使是嵌入式设备也只有大约 2% 的 CPU 使用率,但它执行的事务要少得多——大约十分之一。尽管我们试图尽可能快地获取数据,但这两个系统都只能获得大约 2%。

我的猜测是某些互斥锁被锁定并阻止了一个线程。这是一个纯粹的猜测!系统中有几个线程具有公共数据。也许还有其他可能性,但我怎么知道?

是否可以使用像 valgrind/callgrind 这样的工具来显示系统调用所花费的时间?如果更好的话,我也可以使用 Visual Studio 2012 在 Windows 上运行它。

我们可能不得不尝试遍历代码或其他东西,但不确定我们是否有时间。

感谢任何提示。

谢谢。

【问题讨论】:

嗯 - 想知道这是否有帮助 - --collect-systime= [default: no] 这指定是否应收集系统调用时间的信息 如果你有 VS2012 供你使用,也许the built-in profiler 可能会有一些价值。 刚刚意识到 - 我有 VS2012,但没有高级版或终极版,所以我认为我没有那个选项。 gdb内运行程序,中断程序几次,看看所有线程的堆栈跟踪。我希望所有线程都在等待阻塞网络操作,或者某些线程正在等待锁定一个线程在执行阻塞网络操作时持有的互斥锁。 谢谢 - 是的,这是可能的。谢谢。 【参考方案1】:

Callgrind 是一个很棒的分析器,但它也有一些缺点。特别是,它假设相同的指令总是在相同的时间内执行,并且假设指令计数是最重要的指标。

这对于获取(大部分)可重现的分析结果和详细分析执行了哪些指令是很好的,但是 Callgrind 无法检测到某些类型的性能问题:

等待锁定所花费的时间 睡眠时间(例如,简单的 sleep()/usleep() 调用会有效地减慢您的应用程序,但不会显示在 Callgrind 中) 等待磁盘 I/O 或网络 I/O 所花费的时间 等待换出数据所花费的时间 CPU 缓存命中/未命中的影响(您可以尝试将 Cachegrind 用于此特定主题) 来自 CPU 流水线停顿、分支预测失败以及现代 CPU 的所有其他功能的影响,这些功能可能导致同一指令执行得更快或更慢,具体取决于上下文

使用statistical(或基于样本的)分析器可以很好地检测到这些问题。示例将是Sysprof 和OProfile,或任何类型的“穷人的采样分析器”,例如描述的。在https://***.com/a/378024。 WhozCraig 提到的 VS2012 内置分析器似乎也是一个采样分析器。

虽然统计分析器非常有用,因为它们提供“真实世界”的结果而不是简单的指令计数,但它们可能存在一个缺点,即您无法轻松获得可重现的结果(每次运行的结果都会略有不同) ,并且您需要收集足够数量的样本才能获得详细的结果。

【讨论】:

以上是关于查找可能由线程锁定引起的性能问题(可能)的主要内容,如果未能解决你的问题,请参考以下文章

线程 - AtomicInteger

MySql InnoDB 可能的性能问题

仅当未附加性能分析器时 UI 线程锁定

解决XP系统桌面图标蓝底

无锁链表的性能比锁定链表差

性能调优步骤