我正在研究使用Windows服务器的问题,该服务在具有16个CPU的计算机上占用100%的CPU。
该服务托管自托管的.NET WCF服务。
我收到了一个我在windbg中加载的崩溃转储,以便寻找线索。
所以我尝试过:
!threads:
ThreadCount:646
UnstartedThread:0
BackgroundThread:643
PendingThread:0
DeadThread:2
托管运行时:没有 其中642个线程是Threadpool工作者,如下:
8 29 2a34 000000002068b510 3029220抢占式0000000000000000:0000000000000000 0000000000563f50 0 MTA(Threadpool Worker)
~29s - > !CLRStack
000000003c66eb70 00000000770512fa [GCFrame:000000003c66eb70]
000000003c66ec40 00000000770512fa [GCFrame:000000003c66ec40]
000000003c66ec78 00000000770512fa [HelperMethodFrame:000000003c66ec78]
System.Threading.Monitor.Enter(System.Object)
000000003c66ed70 000007fef7af1c9c System.Threading.TimerQueueTimer.Fire()
000000003c66ede0 000007fef7a6c2f3 System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
000000003c66ee30 000007fef7a6c92a System.Threading.ThreadPoolWorkQueue.Dispatch()
000000003c66f388 000007fef8d57d33 [DebuggerU2MCatchHandlerFrame:000000003c66f388]
~29s - > ķ
00000000
3c66e858 000007fe
fd7010dc ntdll!NtWaitForSingleObject + 0xa
000000003c66e860 000007fe
f8d049bf KERNELBASE!WaitForSingleObjectEx + 0x79
000000003c66e900 000007fe
f8d04977 clr!CLREventBase :: WaitEx + 0x16c
000000003c66e940 000007fe
f8d048f8 clr!CLREventBase :: WaitEx + 0x103
000000003c66e9a0 000007fe
f8e9c5de clr!CLREventBase :: WaitEx + 0x70
000000003c66ea30 000007fe
f8dc5a34 clr!WKS :: GCHeap :: WaitUntilGCComplete + 0x2b
000000003c66ea60 000007fe
f8d0c4f4 clr!Thread :: RareDisablePreemptiveGC + 0x176
000000003c66eaf0 000007fe
f8dd1f3d clr!GCCoop :: GCCoop + 0x3d
000000003c66eb20 000007fe
f8e898cf clr!AwareLock :: Contention + 0x137
000000003c66ebe0 000007fe
f7af1c9c clr!JITutil_MonContention + 0xaf
000000003c66ed70 000007fe
f7a6c2f3 mscorlib_ni + 0x521c9c
000000003c66ede0 000007fe
f7a6c92a mscorlib_ni + 0x49c2f3
000000003c66ee30 000007fe
f8d57d33 mscorlib_ni + 0x49c92a
000000003c66eef0 000007fe
f8d556e6 clr!CallDescrWorkerInternal + 0x83
000000003c66ef30 000007fe
f8d557af clr!CallDescrWorkerWithHandler + 0x4a
000000003c66ef70 000007fe
f8eda2c9 clr!MethodDescCallSite :: CallTargetWorker + 0x2e6
000000003c66f120 000007fe
f8ee51b0 clr!QueueUserWorkItemManagedCallback + 0x2a
000000003c66f200 000007fe
f8ee513e clr!DebuggerU2MCatchHandlerFrame :: DebuggerU2MCatchHandlerFrame + 0xa0
000000003c66f240 000007fe
f8ee50b5 clr!ManagedPerAppDomainTPCount :: DispatchWorkItem + 0x38e
000000003c66f340 000007fe
f8ee51eb clr!ManagedPerAppDomainTPCount :: DispatchWorkItem + 0x2bd
000000003c66f3d0 000007fe
f8eda224 clr!ManagedPerAppDomainTPCount :: DispatchWorkItem + 0x23b
000000003c66f430 000007fe
f8ee6baf clr!ManagedPerAppDomainTPCount :: DispatchWorkItem + 0xb4
000000003c66f5c0 000007fe
f8ee6ab3 clr!ThreadpoolMgr :: ExecuteWorkRequest + 0x4c
000000003c66f5f0 000007fe
f8eda8a6 clr!ThreadpoolMgr :: WorkerThreadStart + 0xf3
000000003c66f6b0 00000000
76c9652d clr!Thread :: intermediateThreadProc + 0x7d
000000003c66f7f0 00000000
7702c541 kernel32!BaseThreadInitThunk + 0xd
000000003c66f820 00000000
00000000 ntdll!RtlUserThreadStart + 0x1d
我很难解释堆栈跟踪,因为他们没有点击我的任何应用程序代码。 他们都只是空闲的线程工,等待工作吗?
答案 0 :(得分:1)
WaitForSingleObject
的线程并不重要,因为它们正在等待并且不占用CPU时间。但请注意,您的转储只是一个快照,在拍摄快照时可能运气不佳。
对于使用WinDbg进行性能分析,您需要在高CPU期间进行多次转储并进行比较。如果他们都有类似的堆栈跟踪,那很好,你可以得出结论。如果它们都非常不同,那几乎是无用的。
命令!runaway
在这里看起来更有趣,因为它列出了每个线程消耗的CPU时间,因此您可以识别高CPU上的CPU时间。再说一次:拥有两个可以比较的快照是有帮助的,因为主线程可能仍然比一些短期100%线程消耗更多的CPU时间。
如果您无法使用性能分析器,SysInternals Procdump可以在高CPU(-n
)上为您生成一系列转储(-c
)。使用-s
设置转储之间的时间。对于.NET,请不要忘记-ma
以获取完整内存。
除此之外,646线程对我来说听起来很多。操作系统本身可能非常忙于安排它们。
答案 1 :(得分:0)
听起来这个问题可能与GC有关。由于这是一个自托管服务,因此默认情况下它将使用Workstation GC,除非您手动启用服务器GC:
http://msdn.microsoft.com/en-us/library/ms229357(v=vs.110).aspx
你有没有尝试过,看看它是否有所作为?
答案 2 :(得分:0)
Microsoft的Perfview可能会有所帮助。从链接:
“去年年底,现任.NET Framework Performance团队架构师的Vance Morrison发布了PerfView,这是.NET开发人员的新性能工具.PerfView可帮助您发现和调查.NET Framework中的性能热点应用程序,使您能够为客户提供始终如一的高性能应用程序。
使用PerfView,您可以执行复杂的CPU性能分析,以解决难以检测的性能问题。 PerfView革命性的分组和折叠功能使我们能够掌握并解决这些难题。“
答案 3 :(得分:0)
使用WPRUI.exe捕获跟踪并使用WPA.exe分析CPU使用情况。
Microsoft解释了如何在以下视频中分析创建的跟踪:
碎片整理工具:#42 - WPT - CPU分析
http://channel9.msdn.com/Shows/Defrag-Tools/Defrag-Tools-42-WPT-CPU-Analysis
答案 4 :(得分:-1)
使用Perfview收集ETW并遵循较大的%数字。
尝试在windbg〜* e!clstack =>中运行所有线程的调用堆栈寻找可重复的代码。