此文仅记录本人初次使用Windbg调试IIS,方便本人或有需要的同学参考!
-------------------------------------------------------------------------
1. WinDbg下载和安装
Install Debugging Tools for Windows 32-bit Version
http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx
Install Debugging Tools for Windows 64-bit Versions
http://www.microsoft.com/whdc/devtools/debugging/install64bit.mspx
建议不要下载winsdk_web.exe在线安装,超慢无法忍受,可直接下载 Windows Driver Kit (WDK) ISO image安装包(600多M好大),安装后在安装目录打开Debuggers/windbg.exe。
2. 设置并下载Windbg下载符号,请按以下步骤在Windbg命令行输入指令(注意下面的.不能去掉):
1) .sympath srv*G:\WinDDK\7600.16385.1\Debuggers\Symbols*http://msdl.microsoft.com/download/symbols (* 注意前面的绝对路径必须存在,不存在自己建立)。
2) !sym noisy
3) .reload安装符号完成。
3.抓取DUMP
推荐使用Procdump进行抓取(详细使用请猛击这里:好用的抓取dump的工具-ProcDump),也可以直接在任务管理器中右键IIS进程w3wp.exe,然后选择“创建转储文件”生成DUMP。
4.分析DUMP
因为需要解决的是高CPU的问题,思路是分析某个线程在进程启动后占用的cpu时间。所以需要取多个dump,看"高CPU时间段"内"占用cpu时间增长最多"的是哪个线程,最终得到的两个文件如下(分别在任务管理器中在不同的时间段取两次DUMP):
打开第一个DUMP,运行!runaway命令可以看到各线程的CPU占用总时间:
Thread Time
18:fdc 0 days 1:20:28.390
19:1370 0 days 1:16:36.359
21:538 0 days 1:08:28.765
22:698 0 days 1:07:55.968
20:1180 0 days 0:58:22.046
138:1284 0 days 0:56:53.890
136:f9c 0 days 0:49:38.609
9:1094 0 days 0:44:26.312
147:db8 0 days 0:25:16.234
149:6f4 0 days 0:22:00.687
148:c8c 0 days 0:20:29.156
13:1108 0 days 0:01:31.562
12:d24 0 days 0:01:27.593
14:5e8 0 days 0:01:26.203
11:ce0 0 days 0:01:06.703
打开第二个DUMP,运行!runaway命令可以看到各线程的CPU占用总时间:
Thread Time
18:fdc 0 days 1:21:09.125
19:1370 0 days 1:20:20.468
21:538 0 days 1:08:43.140
22:698 0 days 1:08:28.812
20:1180 0 days 1:03:01.078
138:1284 0 days 0:57:49.281
136:f9c 0 days 0:55:01.250
9:1094 0 days 0:44:50.781
146:db8 0 days 0:27:10.062
147:c8c 0 days 0:25:17.828
148:6f4 0 days 0:25:03.656
13:1108 0 days 0:01:32.328
将两个DUMP中相同编号的线程结果减一下,可以得出66线程在这段时间内增长得最快,也就是说cpu这段时间内都在完成66线程的事情,那它肯定就是高cpu的原因了。
为了查看66线程对应的托管堆栈,执行以下命令:
1) 加载sos扩展,输入.load C:\Windows\Microsoft.NET\Framework64\v4.0.30319\SOS.dll(32位系统相应改)。
2) 运行~66 s 切换到66线程。
3) 运行!clrstack查看堆栈。
从代码可以看出是StripHTML方法有问题,该方法执行一个正则式剔除所有HTML(取自cnblogs),可见该方法效率十分低下!

剩下的事情就好办了,重写或弃用此方法!
====================== Windbg的其它指令参考 ======================
!threadpool,查看线程池CPU使用量
!runaway,查看线程占用CPU时间,可以从中找到哪个线程占用时间更高。
~number s,number为具体哪个线程的ID。
!clrstack,到具体某个线程后,查看当前线程的托管代码
!name2ee ,找到哪个托管代码模块后,查看MethodTable,EEClass等信息。
!dumpmt,找到相关MethodTable处的相关信息。
!dumpmd,根据MethodDesc找到相关模块信息,比如MethodTable.
!dumpdomain,显示所有域里的程序集,或者根据参数获取指定域。
!savemodule,根据具体程序集地址,把当前程序集的代码生成到指定文件
查看占用内存过高的命令比如:
!eeheap,查看堆中信息,可以查看到大对象。
!dumpheap,查看堆中信息,一般带-min,-stat,-type等参数。
!gcroot,根据堆地址,查看相关模块引用代码信息。
其他命令当然还非常多,也非常有用,需要的时候再翻资料,如果需要很精通windbg+sos,还是老老实实仔细看吧。
本文参考以下文章:
http://www.cnblogs.com/h-hello/articles/1502493.html
http://www.cnblogs.com/Jesses/archive/2011/05/03/2035560.html
http://www.cnblogs.com/Lawson/archive/2011/01/23/1942692.html