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 (Thomas가 제안) 후에 이제 GC 호출을 볼 수 있습니다.
업데이트 1
xperf를 실행 한 후 각 w3wp.exe는 CPU의 약 45 %를 소비합니다. 이들 중 하나를 기준으로 필터링하고 기능별로 그룹화하면 "?"라는 레이블이 붙은 기능이 있습니다. 이는 13.62 %를 차지하고 나머지는 2.67 % 이하입니다. 이 "?"가 무엇인지 어떻게 알 수 있습니까?
업데이트 2
xperf를 다시 실행하면 기능 JIT_MonEnterWorker_InlineGetThread_GetThread_PatchLabel
이 CPU 사용량의 12.31 %를 차지합니다. "?" 기능은 여전히 남아 있습니다.
스택 별 그룹화 :
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 % 이상을 차지합니다 (각 프로세스에 대해 중요하므로 중요합니다).
업데이트 3
wpr.exe를 사용한 후 (@ magicandre1981의 제안) :
wpr.exe -start cpu and wpr -stop result.etl
FormsAuthentication과 중요한 경로에서 Ninject에 대한 불필요한 호출이 CPU 사용량의 약 16 %에 기여한다는 것을 알게되었습니다. 여전히 10 분 이상 실행되는 스레드를 이해하지 못합니다.
업데이트 4
DebugDiag (@leppie의 제안)를 시도했으며 중단 된 스레드가 모두 다음과 유사하다는 것을 확인했습니다.
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
Doing this by hand needs bravery ;) Please check this Official MS DebugDiag 2.2: https://www.microsoft.com/en-us/download/details.aspx?id=49924 it has come with analyzer so you don't have to do with your hand. With DebugDiag, I think you will find your problem faster then ever...
The slow app , could be from the slow code Or maybe it happens from the .NET engine
at first if you had checked the clr.dll if it have problems you can download it and replace it on your computer Else if that it don't have any problem Try this
I think you should review your application codes ,and chick every corner that takes a lot of process and try to balance the code operations load between CPU and RAM . loops , object initialization Or recursion functions etc.. all makes load on CPU Try to store the shard objects on static Or Constant
'developer tip' 카테고리의 다른 글
Google App Engine을 사용할 때 유효하지 않거나 누락 된 SSL 인증서 (0) | 2020.11.22 |
---|---|
OpenCV undistortPoints 및 triangulatePoint가 이상한 결과 (스테레오)를 제공합니다. (0) | 2020.11.22 |
XE3에서 자동 업데이트로 라이브 바인딩 (XE2 에서처럼 Notify ()를 호출 할 필요 없음) (0) | 2020.11.22 |
WebRTC AGC (자동 이득 제어) (0) | 2020.11.22 |
JAAS 인증 확인을 Shiro에 위임하려면 어떻게해야합니까? (0) | 2020.11.22 |