Pod dużym obciążeniem nasza aplikacja sprawia, że sprawny serwer przechodzi na 100% wykorzystanie procesora. Czytanie zrzutu procesu, patrząc na wątki, niektóre z nich są 10 minut w górę. Żaden z nich nie daje mi żadnego wglądu podczas używania! CLRStack. !xperf WinDBG C# .NET 4.5.2 Aplikacja - Opis zrzutu procesu
Uciekinier daje mi:
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
...
Wywołanie DumpStack na jeden z tych wątków, otrzymuję:
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
Co to jest mi powiedzieć? Widzę wiele wywołań do CLR, ale nie mogę zrozumieć, gdzie byłby problem. Po .reload (sugerowanym przez Thomasa) teraz widzę wywołania GC.
Aktualizacja 1
Po uruchomieniu xperf każdy w3wp.exe coś zużywa około 45% CPU. Filtrowanie według jednego z nich i grupowanie według funkcji zawiera funkcję oznaczoną jako "?" odpowiada za 13,62%, a pozostałe 2,67% lub mniej. Jak mogę się dowiedzieć, co to jest "?"?
Aktualizacja 2
Ran xperf ponownie, a funkcja JIT_MonEnterWorker_InlineGetThread_GetThread_PatchLabel
jest odpowiedzialny za 12.31% wykorzystania procesora. "?" funkcja wciąż tam jest.
Grupowanie przez stos:
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
Jak widać, te dwa są odpowiedzialne za ponad 27% zużycia procesora (dla każdego procesu, więc jest to istotne).
Aktualizacja 3
Po użyciu wpr.exe (sugestia przez @ magicandre1981):
wpr.exe -start cpu and wpr -stop result.etl
I okazało się, że FormsAuthentication i niepotrzebne rozmowy do Ninject na ścieżce krytycznej były przyczyniając się do około 16% użycia procesora. Nadal nie rozumiem wątków trwających 10 minut lub dłużej.
Aktualizacja 4
Próbowano DebugDiag (sugestia @leppie) i tak potwierdza się, że nici wiszące są podobne do:
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
lub z powodu 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
lub
[[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
Coś, co czeka w 'WaitForSingleObjectEx()' nie zużywają CPU, ponieważ czeka i nie robi pracę. Wątki związane z impasem również nie zużywają procesora, ponieważ wszystkie będą czekały na zasoby. –
@Thomas Każdy pomysł, w jaki sposób mogę uzyskać cokolwiek użytecznego z tego miejsca? Odnośnie liczby cyfr dla numeru wątku, ogólnie mam zarządzany kod runnig wątki z 3 cyfr. Nie wierzę, że to jest problem. –
@ Thomas Po .Symfix nadal mam te same wartości. Już wcześniej mogłem zobaczyć kod zarządzany, więc nie naprawię go jako problemu z symbolem. –