xperf WinDBG C#.NET 4.5.2应用程序 – 了解进程转储

在沉重的负载下,我们的应用程序正在使一个强大的服务器达到100%的CPU使用率。 读取进程转储,看看线程,其中一些是10分钟。 当使用CLRStack时,他们没有给我任何的洞察力。

!失控给了我:

0:030> !runaway User Mode Time Thread Time 53:2e804 0 days 0:10:04.703 30:31894 0 days 0:07:51.593 33:47100 0 days 0:07:24.890 42:11e54 0 days 0:06:45.875 35:35e18 0 days 0:06:07.578 41:54464 0 days 0:05:49.796 47:57700 0 days 0:05:45.000 44:3c2d4 0 days 0:05:44.265 32:3898c 0 days 0:05:43.593 50:54894 0 days 0:05:41.968 51:5bc58 0 days 0:05:40.921 43:14af4 0 days 0:05:40.734 48:35074 0 days 0:05:40.406 ... 

调用这些线程之一的DumpStack,我得到:

 0000001ab442f900 00007ff9ef4c1148 KERNELBASE!WaitForSingleObjectEx+0x94, calling ntdll!NtWaitForSingleObject 0000001ab442f980 00007ff9e920beb2 clr!SVR::gc_heap::compute_new_dynamic_data+0x17b, calling clr!SVR::gc_heap::desired_new_allocation 0000001ab442f9a0 00007ff9e90591eb clr!CLREventWaitHelper2+0x38, calling kernel32!WaitForSingleObjectEx 0000001ab442f9b0 00007ff9e90e0d2c clr!WriteBarrierManager::UpdateEphemeralBounds+0x1c, calling clr!WriteBarrierManager::NeedDifferentWriteBarrier 0000001ab442f9e0 00007ff9e9059197 clr!CLREventWaitHelper+0x1f, calling clr!CLREventWaitHelper2 0000001ab442fa40 00007ff9e9059120 clr!CLREventBase::WaitEx+0x70, calling clr!CLREventWaitHelper 0000001ab442fa70 00007ff9ef4c149c KERNELBASE!SetEvent+0xc, calling ntdll!NtSetEvent 0000001ab442faa0 00007ff9e90ef1e1 clr!SVR::gc_heap::set_gc_done+0x22, calling clr!CLREventBase::Set 0000001ab442fad0 00007ff9e90e9331 clr!SVR::gc_heap::gc_thread_function+0x8a, calling clr!CLREventBase::WaitEx 0000001ab442fb00 00007ff9e92048e7 clr!SVR::gc_heap::gc_thread_stub+0x7a, calling clr!SVR::gc_heap::gc_thread_function 0000001ab442fb60 00007ff9e91a0318 clr!Thread::CLRSetThreadStackGuarantee+0x48, calling kernel32!SetThreadStackGuaranteeStub 0000001ab442fb90 00007ff9e91a01ef clr!Thread::CommitThreadStack+0x10, calling clr!Thread::CLRSetThreadStackGuarantee 0000001ab442fbd0 00007ff9e910df0b clr!ClrFlsSetValue+0x57, calling kernel32!SetLastErrorStub 0000001ab442fc00 00007ff9e92048dc clr!SVR::gc_heap::gc_thread_stub+0x6f, calling clr!_chkstk 0000001ab442fc40 00007ff9f0d316ad kernel32!BaseThreadInitThunk+0xd 0000001ab442fc70 00007ff9f1e54409 ntdll!RtlUserThreadStart+0x1d 

这是什么告诉我? 我看到很多电话给CLR,但我不明白问题在哪里。 在.reload(托马斯build议)之后,我可以看到GC调用。

更新1

运行xperf之后,每个w3wp.exe消耗约45%的CPU。 通过其中之一进行过滤和按function分组,有一个function标记为“?” 这是负责13.62%,其他2.67%或更less。 我如何设法知道这个“?”是什么?

更新2

再次运行xperf,函数JIT_MonEnterWorker_InlineGetThread_GetThread_PatchLabel负责CPU使用率的12.31%。 “?” function仍然停留在那里。

按堆栈分组:

 Line #, Stack, Count, Weight (in view), TimeStamp, % Weight 2, |- ?!?, 501191, 501222.365294, , 35.51 3, | |- clr.dll!JITutil_MonContention, 215749, 215752.552227, , 15.28 4, | |- clr.dll!JIT_MonEnterWorker_InlineGetThread_GetThread_PatchLabel, 170804, 170777.100191, , 12.10 

正如你所看到的,这两个CPU负责超过27%的CPU使用率(每个进程,所以它是重要的)。

更新3

使用wpr.exe后(build议由@ magicandre1981):

 wpr.exe -start cpu and wpr -stop result.etl 

我发现FormsAuthentication以及在关键path上对Ninject的一些不必要的调用都占CPU使用率的16%左右。 我仍然不明白10分钟或更长时间运行的线程。

更新4

试过DebugDiag(来自@leppie的build议),它只是确认挂起的线程都类似于:

 Thread ID: 53 Total CPU Time: 00:09:11.406 Entry Point for Thread: clr!Thread::intermediateThreadProc Thread ID: 35 Total CPU Time: 00:07:26.046 Entry Point for Thread: clr!SVR::gc_heap::gc_thread_stub Thread ID: 50 Total CPU Time: 00:07:01.515 Entry Point for Thread: clr!SVR::gc_heap::gc_thread_stub Thread ID: 29 Total CPU Time: 00:06:02.264 Entry Point for Thread: clr!SVR::gc_heap::gc_thread_stub Thread ID: 31 Total CPU Time: 00:06:41.281 Entry Point for Thread: clr!SVR::gc_heap::gc_thread_stub 

或由于StackExchange.Redis:

 DomainBoundILStubClass.IL_STUB_PInvoke(Int32, IntPtr[], IntPtr[], IntPtr[], TimeValue ByRef)+e1 [[InlinedCallFrame] (StackExchange.Redis.SocketManager.select)] StackExchange.Redis.SocketManager.select(Int32, IntPtr[], IntPtr[], IntPtr[], TimeValueByRef) StackExchange.Redis.SocketManager.ReadImpl()+889 StackExchange.Redis.SocketManager.Read()+66 

要么

 [[GCFrame]] [[HelperMethodFrame_1OBJ] (System.Threading.Monitor.ObjWait)] System.Threading.Monitor.ObjWait(Boolean, Int32, System.Object) mscorlib_ni!System.Threading.Monitor.Wait(System.Object, Int32)+19 StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl[[System.__Canon, mscorlib]](StackExchange.Redis.Message, StackExchange.Redis.ResultProcessor`1, StackExchange.Redis.ServerEndPoint)+24f StackExchange.Redis.RedisBase.ExecuteSync[[System.__Canon, mscorlib]](StackExchange.Redis.Message, StackExchange.Redis.ResultProcessor`1, StackExchange.Redis.ServerEndPoint)+77 [[StubHelperFrame]] StackExchange.Redis.RedisDatabase.SetMembers(StackExchange.Redis.RedisKey, StackExchange.Redis.CommandFlags)+ee 

这样做需要勇气;)请检查官方MS DebugDiag 2.2: https : //www.microsoft.com/en-us/download/details.aspx? id = 49924它已与分析器,所以你没有做你的手。 有了DebugDiag ,我想你会发现你的问题更快,然后

缓慢的应用程序,可能是从慢代码或者也许它发生在.NET引擎

首先如果你检查了clr.dll,如果有问题,你可以下载它,并将其replace到你的电脑上否则,如果它没有任何问题试试这个

我认为你应该检查你的应用程序代码,并挑选需要大量进程的每个angular落,并尝试平衡CPU和RAM之间的代码操作负载。 循环,对象初始化或recursion函数等。所有使CPU上的负载尝试将分片对象存储在静态或常量上