windbg 分析 .net 的dump文件我的执行步骤如下
1.file 选项下设置符号变量srvc:\symbolshttp://msdl.microsoft.com/download/symbols
试试 https://q.cnblogs.com/q/98872/ 中的方法
问题的错误提示现在看来应该是非托管线程导致的,重新分析dump,执行!syncblk结果如下
Index SyncBlock MonitorHeld Recursion Owning Thread Info SyncBlock Owner
111 031d0750 194 0 00000000 none 0c6e4a94 System.Threading.TimerQueue
-----------------------------
Total 425
CCW 2
RCW 3
ComClassFactory 0
Free 254
这个MonitorHeld 为偶数,而网上解释说要么是奇数要么是0。这个dump当时的cpu利用率为100%,
CPU utilization: 100%
Worker Thread: Total: 145 Running: 145 Idle: 0 MaxLimit: 8191 MinLimit: 32
Work Request in Queue: 0
--------------------------------------
Number of Timers: 1
--------------------------------------
Completion Port Thread:Total: 1 Free: 1 MaxFree: 64 CurrentLimit: 1 MaxLimit: 1000 MinLimit: 32
查看托管的堆栈信息发现有145 个 都在执行
System.Threading.Monitor.ReliableEnter(System.Object, Boolean ByRef)
3c93ed04 71e8597d System.Threading.TimerQueueTimer.Fire()
3c93ed44 71e762c1 System.Threading.TimerQueue.FireQueuedTimerCompletion(System.Object)
3c93ed48 71ece174 System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
3c93ed5c 71ecd949 System.Threading.ThreadPoolWorkQueue.Dispatch()
3c93edac 71ecd7f5 System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
3c93efd8 73643e22 [DebuggerU2MCatchHandlerFrame: 3c93efd8]
3c93f044 73643e22 [ContextTransitionFrame: 3c93f044]
3c93f1d0 73643e22 [DebuggerU2MCatchHandlerFrame: 3c93f1d0]
Stack Overflow上有搜到一片文章
https://stackoverflow.com/questions/19192115/syncblk-with-odd-monitorheld-count-and-no-owner
because an orphaned SyncBlk will usually lead to a deadlock in short order
所以我cpu利用率高难道是因为同步块的问题么,求大佬帮忙
@GYY_顽石: 建议仔细检查代码
@dudu: 好吧,我再仔细看看吧,CPU是突然飚到100%然后一会就下去了
@GYY_顽石: 耗CPU大户之一是正则表达式对文本的处理
@GYY_顽石: 另外,充分利用缓存,缓存不仅能减少数据库的压力,也能减少CPU的压力
@dudu: 首先感谢大佬这么热情的帮助,缓存基本上我没怎么使用(后续再加上来),使用的ODP.NET 直接差的库,不过频率应该不高,抓的dump包基本上都是执行了OracleInternal.SelfTuning.OracleTuner.DoScan()
后面的线程全都是在System.Threading.Monitor.ReliableEnter,具体原因还待查。
再次感谢大佬,有结果我会及时更新问题状态,谢谢!
@dudu:
问题应该是找出来了,底层不知道谁写了个Timer,代码类似下面
_timer = new Timer(1000);
_timer.Elapsed += (s, e) =>
{
//Todo...
};
每次new一个这个对象都要创建一个定时器,而且在disopse时并没有注销此事件。
我观察到的现象是这样会导致内存一直在增长,线程数量也是,最后就导致CPU占用和内存占用过高,对于exe程序还会导致内存溢出现象。
观察dump里面,!dumpheap -stat 列出来的Timer对象也是占了很大一部分,所以基本确定是Timer过多导致CPU和内存占用过高。至于原因我觉的应该是Timer 的Elapsed事件并没有及时注销,导致相应的对象一直存留在系统中,且每个Timer好像是要占用一个线程(出现问题时,dump里面有500多个线程),这种现象需要观察很久(几天时间)才会出现这样的问题。
分析dump的方法参考 windbg调试内存泄露
@GYY_顽石: 谢谢分享
@dudu: 还得感谢大佬指点 :)