自托管WCF服务最大化CPU负载

时间:2014-10-23 12:36:28

标签: multithreading wcf load cpu windbg

我正在研究使用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
      00000000 3c66e860 000007fe f8d049bf KERNELBASE!WaitForSingleObjectEx + 0x79
      00000000 3c66e900 000007fe f8d04977 clr!CLREventBase :: WaitEx + 0x16c
      00000000 3c66e940 000007fe f8d048f8 clr!CLREventBase :: WaitEx + 0x103
      00000000 3c66e9a0 000007fe f8e9c5de clr!CLREventBase :: WaitEx + 0x70
      00000000 3c66ea30 000007fe f8dc5a34 clr!WKS :: GCHeap :: WaitUntilGCComplete + 0x2b
      00000000 3c66ea60 000007fe f8d0c4f4 clr!Thread :: RareDisablePreemptiveGC + 0x176
      00000000 3c66eaf0 000007fe f8dd1f3d clr!GCCoop :: GCCoop + 0x3d
      00000000 3c66eb20 000007fe f8e898cf clr!AwareLock :: Contention + 0x137
      00000000 3c66ebe0 000007fe f7af1c9c clr!JITutil_MonContention + 0xaf
      00000000 3c66ed70 000007fe f7a6c2f3 mscorlib_ni + 0x521c9c
      00000000 3c66ede0 000007fe f7a6c92a mscorlib_ni + 0x49c2f3
      00000000 3c66ee30 000007fe f8d57d33 mscorlib_ni + 0x49c92a
      00000000 3c66eef0 000007fe f8d556e6 clr!CallDescrWorkerInternal + 0x83
      00000000 3c66ef30 000007fe f8d557af clr!CallDescrWorkerWithHandler + 0x4a
      00000000 3c66ef70 000007fe f8eda2c9 clr!MethodDescCallSite :: CallTargetWorker + 0x2e6
      00000000 3c66f120 000007fe f8ee51b0 clr!QueueUserWorkItemManagedCallback + 0x2a
      00000000 3c66f200 000007fe f8ee513e clr!DebuggerU2MCatchHandlerFrame :: DebuggerU2MCatchHandlerFrame + 0xa0
      00000000 3c66f240 000007fe f8ee50b5 clr!ManagedPerAppDomainTPCount :: DispatchWorkItem + 0x38e
      00000000 3c66f340 000007fe f8ee51eb clr!ManagedPerAppDomainTPCount :: DispatchWorkItem + 0x2bd
      00000000 3c66f3d0 000007fe f8eda224 clr!ManagedPerAppDomainTPCount :: DispatchWorkItem + 0x23b
      00000000 3c66f430 000007fe f8ee6baf clr!ManagedPerAppDomainTPCount :: DispatchWorkItem + 0xb4
      00000000 3c66f5c0 000007fe f8ee6ab3 clr!ThreadpoolMgr :: ExecuteWorkRequest + 0x4c
      00000000 3c66f5f0 000007fe f8eda8a6 clr!ThreadpoolMgr :: WorkerThreadStart + 0xf3
      00000000 3c66f6b0 00000000 76c9652d clr!Thread :: intermediateThreadProc + 0x7d
      00000000 3c66f7f0 00000000 7702c541 kernel32!BaseThreadInitThunk + 0xd
      00000000 3c66f820 00000000 00000000 ntdll!RtlUserThreadStart + 0x1d

我很难解释堆栈跟踪,因为他们没有点击我的任何应用程序代码。 他们都只是空闲的线程工,等待工作吗?

5 个答案:

答案 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可能会有所帮助。从链接:

http://blogs.msdn.com/b/dotnet/archive/2012/10/09/improving-your-app-s-performance-with-perfview.aspx

“去年年底,现任.NET Framework Performance团队架构师的Vance Morrison发布了PerfView,这是.NET开发人员的新性能工具.PerfView可帮助您发现和调查.NET Framework中的性能热点应用程序,使您能够为客户提供始终如一的高性能应用程序。

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

答案 3 :(得分:0)

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

enter image description here

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

碎片整理工具:#42 - WPT - CPU分析
http://channel9.msdn.com/Shows/Defrag-Tools/Defrag-Tools-42-WPT-CPU-Analysis

答案 4 :(得分:-1)

使用Perfview收集ETW并遵循较大的%数字。

尝试在windbg〜* e!clstack =>中运行所有线程的调用堆栈寻找可重复的代码。