Multithreading 自托管WCF服务最大化cpu负载

Multithreading 自托管WCF服务最大化cpu负载,multithreading,wcf,load,cpu,windbg,Multithreading,Wcf,Load,Cpu,Windbg,我正在研究Windows服务工作中的一个问题,该服务在一台有16个CPU的机器上占用100%的CPU 该服务正在托管自托管的.NET WCF服务 为了寻找线索,我收到了一个在windbg中加载的崩溃转储文件 所以我试过: !!线程: 线程数:646 未启动的线程:0 背景线索:643 PendingThread:0 死线:2 托管运行时:否 其中642个线程是线程池工作线程,如下所示: 8 29 2a34 00000000 2068B510 3029220抢占式0000000000000000:

我正在研究Windows服务工作中的一个问题,该服务在一台有16个CPU的机器上占用100%的CPU

该服务正在托管自托管的.NET WCF服务

为了寻找线索,我收到了一个在windbg中加载的崩溃转储文件

所以我试过:

!!线程:

线程数:646 未启动的线程:0 背景线索:643 PendingThread:0 死线:2 托管运行时:否 其中642个线程是线程池工作线程,如下所示: 8 29 2a34 00000000 2068B510 3029220抢占式0000000000000000:0000000000000000000000 0000000000 563F50 0 MTA线程池工作线程

~29s->!CLRStack

00000000 3C66EB70 00000000 770512FA[GCFrame:00000000 3C66EB70] 00000000 3C66EC40 00000000 770512FA[GCFrame:00000000 3C66EC40] 00000000 3C66EC78 00000000 770512FA[HelperMethodFrame:00000000 3C66EC78]System.Threading.Monitor.EnterSystem.Object 00000000 3C66ED70 000007fef7af1c9c System.Threading.TimerQueueTimer.Fire 00000000 3C66EDE0 00000 7FEF7A6C2F3 System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem 00000000 3C66EE30 00000 7FEF7A6C92A System.Threading.ThreadPoolWorkQueue.Dispatch 00000000 3C66F388 000007 FEF8D57D33[DebuggerU2MCatchHandlerFrame:00000000 3C66F388]

~29s->K

00000000 3C66E858 000007 FEFD7010DC ntdll!NtWaitForSingleObject+0xa 00000000 3C66E860 00000 7FEF8D049BF内核库!WaitForSingleObjectEx+0x79 00000000 3C66E900 00000 7FEF8D04977 clr!CLREventBase::WaitEx+0x16c 00000000 3C66E940 00000 7FEF8D048F8 clr!CLREventBase::WaitEx+0x103 00000000 3C66E9A000000 7FEF8E9C5DE clr!CLREventBase::WaitEx+0x70 00000000 3C66EA30 00000 7FEF8DC5A34 clr!WKS::GCHeap::WaitUntilGCComplete+0x2b 00000000 3C66EA60 00000 7FEF8D0C4F4 clr!线程::RareDisablePreemptiveGC+0x176 00000000 3C66EAF000000 7FEF8DD1F3D clr!GCCoop::GCCoop+0x3d 00000000 3C66EB20 00000 7FEF8E898CF clr!AwareLock::争用+0x137 00000000 3C66EB00 00000 7FEF7AF1C9C clr!JITutil_mon争用+0xaf 00000000 3C66ED70 00000 7FEF7A6C2F3 mscorlib_ni+0x521c9c 00000000 3C66ED00 00000 7FEF7A6C92A mscorlib_ni+0x49c2f3 00000000 3C66EE30 00000 7FEF8D57D33 mscorlib_ni+0x49c92a 00000000 3C66EEF000000 7FEF8D556E6 clr!CallDescrWorkerInternal+0x83 00000000 3C66EF30 00000 7FEF8D557AF clr!CallDescrWorkerWithHandler+0x4a 00000000 3C66EF70 000007 FEF8EDA2C9 clr!MethodDescrCallSite::CallTargetWorker+0x2e6 00000000 3C66F120 00000 7FEF8EE51B0 clr!QueueUserWorkItemManagedCallback+0x2a 00000000 3C66F200 00000 7FEF8EE513E clr!DebuggerU2MCatchHandlerFrame::DebuggerU2MCatchHandlerFrame+0xa0 00000000 3C66F240 00000 7FEF8EE50B5 clr!ManagedPerAppDomainMaintPCount::DispatchWorkItem+0x38e 00000000 3C66F340 00000 7FEF8EE51EB clr!ManagedPerAppDomainMaintpCount::DispatchWorkItem+0x2bd 00000000 3C66F3D000000 7FEF8EDA224 clr!ManagedPerAppDomainMaintPCount::DispatchWorkItem+0x23b 00000000 3C66F430 00000 7FEF8EE6BAF clr!ManagedPerAppDomainMaintpCount::DispatchWorkItem+0xb4 00000000 3C66F5C000000 7FEF8EE6AB3 clr!ThreadpoolMgr::ExecuteWorkRequest+0x4c 00000000 3C66F5F000000 7FEF8EDA8A6 clr!ThreadpoolMgr::WorkerThreadStart+0xf3 00000000 3C66F6B000000000 76C9652D clr!线程::intermediateThreadProc+0x7d 00000000 3C66F7F0 00000000 7702C541内核32!BaseThreadInitThunk+0xd 00000000 3C66F820 0000000000000000 ntdll!RtlUserThreadStart+0x1d

我很难解释堆栈跟踪,因为它们没有命中我的任何应用程序代码。 他们都是闲散的工人,在等待工作吗

带有WaitForSingleObject的线程不是关键线程,因为它们正在等待并且不消耗CPU时间。但是请注意,您的转储只是一个快照,您在拍摄快照时可能运气不好

对于WinDbg的性能分析,您需要在高CPU期间进行几个转储,并对它们进行比较。如果它们都有相似的堆栈跟踪,那么这很好,您可以得出一些结论。如果它们都很不一样,那几乎没用

命令!Runway在这里似乎更有趣,因为它列出了每个线程消耗的CPU时间,所以您可以识别哪些线程的CPU占用率较高。同样:拥有两个可以比较的快照是很有帮助的,因为主线程总的CPU时间消耗量可能仍然比一些短生命的100%线程要多

如果您不能使用性能分析器,可以在高CPU-c上为您生成一系列转储-n。使用-s设置转储之间的时间。对于.NET,不要忘了-ma代表完整内存


除此之外,646个线程对我来说听起来很多。操作系统本身可能正忙于调度它们。

听起来这个问题可能与GC有关。由于这是一个自托管服务,因此默认情况下它将使用工作站GC,除非您手动启用服务器GC:


你试过了吗?看看有没有什么不同?

微软的Perfview可能会有帮助。从链接:

去年年底,万斯·莫里森(Vance Morrison),目前是.NET的架构师 Framework Performance team发布了PerfView,这是一种面向.NET开发人员的新性能工具。PerfView可帮助您发现和调查.NET Framework应用程序中的性能热点,并使您能够向客户提供一致的高性能应用程序


使用PerfView,您可以执行复杂的CPU性能分析,以解决难以检测的性能问题。PerfView革命性的分组和折叠功能使我们能够抓住并解决这些难题。

使用WPRUI.exe捕获跟踪并使用WPA.exe分析CPU使用情况

Microsoft在以下视频中解释了如何分析创建的跟踪:

碎片整理工具:42-WPT-CPU分析

使用Perfview收集ETW,并遵循较大的百分比数字


尝试在windbg~*e中跑步!clstack=>所有线程的调用堆栈都会寻找可重复的代码。

这真的是答案吗?听起来更像是一个评论。这是一个有根据的猜测,基于看到相当多的自托管WCF服务遭受同样的问题,并且事实上显示的堆栈跟踪清楚地表明,如果分配了大量对象,线程正在等待GC完成,那么工作站GC将对16进程的机器产生重大影响。我当然可能错了,但值得一试。听起来很有道理-我正在切换到服务器gc,正在等待部署,看看它是否会改变任何东西!什么事!逃跑报告?如果它在顶部显示的线程不是线程池工作线程,那么它可能会告诉您违规者。否则,请查看为什么有这么多线程-646太多了。使用Microsoft SysInternals的ProcessExplorer,您可以打开进程详细信息,查看线程列表以及线程占用的CPU量。它还可以加载符号并向您显示相关线程的入口点。找出哪些线程正在使用CPU,然后调试那些特定的线程。您尝试过xperf/WPA吗?