使用Windbg调试高CPU问题

      公司的后台程序经常会达到跑满CPU的情况,想解决,但是没有什么头绪,打log也看不到什么。搁置了很久,一直都是重启了事。最近决定对这个问题进行研究,使用的工具是Windbg。

      之前的文章使用Windbg调试StackOverflowException异常也有介绍过使用windbg解决一个疑难杂症,不过那时候对于windbg的使用简直是肤浅入门的水平(现在也是知道了些皮毛而已,windbg功能确实强大)。这次使用windbg在前半段时间仍旧看不出什么有用的信息,后来仔细看了一些文章,主要是逆心:随笔分类 - 调试:Windbg,SOS的调试系列文章,其中最大收益的一篇文章是SOS 调试扩展 (SOS.dll) 《第五篇》,从中学到了更多有效的调试命令和技巧,终于看到了一些有效的信息,主要是详细的调用堆栈和对象分配过程,结合代码推导出出现问题的死循环代码所在,最终解决了问题。

      现在主要是介绍一些这次调试过程中常用的命令:

.sympath[+] pdb路径

#设置调试符号文件路径,+表示在原基础上添加新的路径。我是把调试过程中下载的pdb文件放到一起,将其设置为基础路径,从而不用每次调试都重新下载,再把源项目的pdb文件+进来。

.symfix+ pdb路径

#设置符号文件缓存路径,调试中没加载到的pdb会从服务器上下载,这个缓存路径一般设置为专门存放pdb文件的基础路径。

.reload

#设置符号文件路径后不会自动加载的,需要用这个命令重新加载

.loadby sos clr

#自动加载调试扩展sos.dll,不用指定版本号

!threadpool

#查看进程所占CPU和各个线程情况

!threads [-special]

#显示所有托管线程

~#s

#切换到第#号线程

!clrstack

#查看当前线程的托管代码调用堆栈

kb

#查看当前线程的非托管代码调用堆栈

!dumpstack

#上面两个命令的综合,可以查看托管和非托管代码调用堆栈

!dso

#查看当前线程对象分配过程

      在这次调试过程中,由于之前只会使用!clrstackkb两个命令,只看到线程中最终出问题的代码,但是无法定位,因为只显示是系统的ArrayCopy函数,后来使用!dumpstack命令,所有调用过程一目了然,但是仍然不清楚为何会导致高CPU,这里不会显示死循环的无限调用,只看到有两次ArrayCopy的调用。之后只能查看这个ArrayCopy的对象,就是使用的!dso命令,看到最新的对象里有两个byte[],其中一个竟然有36944个字节,这里是消息处理过程,由代码断定不会产生这么大的消息,这个大对象应该就是问题所在,一开始怀疑是GC,因为以为是死循坏的话,调用堆栈应该会显示多次调用。但是觉得只是分配了一次这个对象而已,也不是特别大,而且看到代码里有段while循环,因此怀疑是死循环问题,研读了下代码,结合!dso看到的一些数据推导,最终确定是出现了不合法的消息,解析过程中按照协议解析而不排除数据出错的话,确实会导致死循环。

posted @ 2016-12-01 15:45  死鱼眼の猫  阅读(904)  评论(0编辑  收藏  举报