线程如何使用少于 100% 的挂壁时间?
Posted
技术标签:
【中文标题】线程如何使用少于 100% 的挂壁时间?【英文标题】:How can a thread use less than 100% wall time? 【发布时间】:2011-06-24 04:30:44 【问题描述】:在分析应用程序时(使用 dotTrace),我注意到一件非常奇怪的事情。我使用了“墙上时间”测量,理论上这应该意味着所有线程都会运行相同的时间。
但事实并非如此:某些线程(实际上是我最感兴趣的线程)显示的总时间大约是其他线程的 2 倍。例如,分析运行了 230 秒,大多数 线程报告在线程中花费了 230 秒,但 5 个线程仅显示 100-110 秒。这些不是线程池线程,它们肯定是在分析开始之前创建和启动的。
这是怎么回事?
更新我将添加更多可能相关或不相关的信息。有问题的应用程序(它是一个游戏服务器)有大约 20-30 个持续运行的线程。大多数线程都遵循简单的模式:它们检查传入队列的工作,如果有的话就开始工作。线程函数的代码如下所示:
while(true)
if(TryDequeueWork()) // if queue is not empty
DoWork(); // do whatever is was on top
else
m_WaitHandle.WaitOne(MaxTimeout); // m_WaitHandle gets signaled when work is added to queue
显示奇怪时间的线程是这样的,除了它们服务于多个队列,像这样:
while(true)
bool hasAnyWork=false;
foreach(var queue in m_Queues)
if(queue.TryDequeueWork())
hasAnyWork=true;
DoWork();
if(!hasAnyWork)
m_WaitHandle.WaitOne(MaxTimeout);
奇怪的线程除了日志之外不做任何 IO。其他不奇怪的线程也进行日志记录。在分析器中报告等待 WaitHandle 所花费的时间;实际上,一些不奇怪的线程几乎将所有时间都花在等待上(因为它们从来没有任何工作)。
应用程序在 8 核虚拟机(VPS 主机)上运行。我不知道那里用的是什么物理处理器。
【问题讨论】:
我今天的疯狂猜测:报告仅显示用户模式时间,而数量较少的线程正在花费时间等待内核对象。 (即 I/O) 我和一位同事在分析在超线程 CPU (Sandy Bridge) 上收集的 ETW 跟踪时发现了一些奇怪的结果。你的 CPU 是超线程的吗? 【参考方案1】:他们可能在分析器完成之前完成了吗?
【讨论】:
好主意,但不,他们没有。【参考方案2】:只有在
您的机器的内核数至少与线程数一样多 线程什么都不做,只会消耗 CPU 周期,并且永远不会被同步对象(如 lock)或 I/O 请求阻塞。两者都不太可能,很少有问题可以很好地扩展。 Amdahl's law 是相关的。
【讨论】:
呃,是的,但是“100% 挂壁时间”应该是什么意思呢?我只能猜测线程时间等于程序运行时间的100%。 是的,这正是它应该的意思。分析器运行了 230 秒。这意味着所有线程(除了那些在分析期间启动和/或完成的线程)也运行了 230 秒。但根据 dotTrace 有些没有!这就是我不明白的。 嗯,我的回答很相关。我无法帮助您猜测,您甚至没有描述您拥有多少线程和多少内核,也没有描述这些线程如何相互交互以及它们执行什么样的工作。 VS2010 Ultimate 版本中内置了一个不错的并发分析器,如果您不知道这些线程如何交互,它确实需要工具。以上是关于线程如何使用少于 100% 的挂壁时间?的主要内容,如果未能解决你的问题,请参考以下文章
当 CPU 负载为 100%(主要使用 C++ 和 Qt)时,如何保持 UI 响应?