首页 新闻 搜索 专区 学院

Windbg 分析.net cpu占用过高 !clrstack 出错

0
悬赏园豆:15 [已解决问题] 解决于 2018-11-06 09:26

windbg 分析 .net 的dump文件我的执行步骤如下
1.file 选项下设置符号变量srvc:\symbolshttp://msdl.microsoft.com/download/symbols

  1. .loadby sos
  2. !sym noisy .cordll -ve -u -l
  3. !runaway
    5.切换到占用cpu时间最多的线程 ~18s
    6.查看堆栈!clrstack
    7.出错信息如下
    0:018> !clrstack
    OS Thread Id: 0x7658 (18)
    Child SP IP Call Site
    GetFrameContext failed: 1
    00000000 00000000
    这个怎么解释呢,求解答
GYY_顽石的主页 GYY_顽石 | 初学一级 | 园豆:20
提问于:2018-08-24 18:25
< >
分享
最佳答案
0

试试 https://q.cnblogs.com/q/98872/ 中的方法

收获园豆:15
dudu | 高人七级 |园豆:37617 | 2018-08-24 22:55

问题的错误提示现在看来应该是非托管线程导致的,重新分析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_顽石 | 园豆:20 (初学一级) | 2018-08-30 17:47

@GYY_顽石: 建议仔细检查代码

dudu | 园豆:37617 (高人七级) | 2018-08-30 17:51

@dudu: 好吧,我再仔细看看吧,CPU是突然飚到100%然后一会就下去了

GYY_顽石 | 园豆:20 (初学一级) | 2018-08-30 17:52

@GYY_顽石: 耗CPU大户之一是正则表达式对文本的处理

dudu | 园豆:37617 (高人七级) | 2018-08-30 17:57

@GYY_顽石: 另外,充分利用缓存,缓存不仅能减少数据库的压力,也能减少CPU的压力

dudu | 园豆:37617 (高人七级) | 2018-08-30 20:47

@dudu: 首先感谢大佬这么热情的帮助,缓存基本上我没怎么使用(后续再加上来),使用的ODP.NET 直接差的库,不过频率应该不高,抓的dump包基本上都是执行了OracleInternal.SelfTuning.OracleTuner.DoScan()
后面的线程全都是在System.Threading.Monitor.ReliableEnter,具体原因还待查。
再次感谢大佬,有结果我会及时更新问题状态,谢谢!

GYY_顽石 | 园豆:20 (初学一级) | 2018-08-31 09:22

@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_顽石 | 园豆:20 (初学一级) | 2018-11-06 09:26

@GYY_顽石: 谢谢分享

dudu | 园豆:37617 (高人七级) | 2018-11-06 10:23

@dudu: 还得感谢大佬指点 :)

GYY_顽石 | 园豆:20 (初学一级) | 2018-11-06 10:23
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册