原文地址:

http://www.cnblogs.com/Lawson/archive/2011/01/23/1942692.html

很早看到windbg+sos方面的知识,一直没仔细学习,也许因为自己做的系统还不够复杂,也没线上真实环境查看的权限,一直没学习这方面的知识,最近几天仔细找了这方面的资料,自己也写了个可能造成高CPU高内存的测试web页面,发现确实不错,即使一个生手,也可以用工具连蒙带骗的猜出哪里出了问题,当然对一些命令和内部标示更熟悉了后,可以更好的找出问题所在,非常值得学习。我在使用过程中,也遇到大量问题,比如系统兼容,软件版本,.net版本等,部分我也没能理解清楚,但现在确实用它找到了程序的问题,因此作个记录,为以后自己或大家查阅资料提供一定的方便。

基本工作:

我用的windbg是6.11.1.404的32位版本,微软官网下载地址:http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx#b,SOS是每个.net框架都自带的,我用的.net4.0的sos.dll,我的在C:\Windows\Microsoft.NET\Framework\v4.0.30319里面,另外我还用了调式的pdb符号文件,如果不下载,可以配置需要的时候自动下载,但下载需要选择操作系统版本。windbg老版本使用过程中报过mscorlib的什么错误,具体记不起了,但以前别人用起过,我确实用不起,换新版本就好了。

配置工作及常用命令:

在windbg主窗口点击File下面的Symbol Search Path,设置符号文件路径,比如我的:C:\Windows\symbols\dll;srv*C:\symbols*http://msdl.microsoft.com/download/symbols,其实C:\symbols才是我下载的符号文件安装位置,http://msdl.microsoft.com/download/symbols这个是必须的,因为找不到符号文件,它会自动从这里下载。也可以从注册表设置,但我没在注册表设置它。

我在调试过程中windbg界面如下:

一般我们找到程序出问题大体的地方,可以直接查看对应代码,如果没源代码,我们同样可以用windbg导出指定程序集地址的代码,然后反编译看到源代码,尤其比如部分dll文件是其他团队的代码,我们看不到的时候。

常用命令比如:

第一步一般是.load C:\Windows\Microsoft.NET\Framework\v4.0.30319\SOS.dll,加载sos,这样才能调试托管代码

查看引起CPU过高命令比如:

!threadpool,查看线程池CPU使用量,我认为WEB的比如iis应用程序池进程w3wp如果CPU使用过高,那查看线程池命令肯定看的出来过高,这个是我自己的理解,c/s的就不一定了。

!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,还是老老实实仔细看吧。

开始调试:

一般分析dump文件方式,可以直接附加进程分析,也可以保存dump文件,再单独线下分析。  在线调试,直接Attach to a process就可以了,一般线下调试,可以用windbg的

adplus.vbs生成dump文件,命令如下:adplus -hang -o d:\dump -p 1234,其中hang表示附加到进程,如果是—crash,则为目标进程崩溃的时候抓取,-o后面的参数表示dump文件放到说明位置,-p后面的数字为进程的PID,也可以是-pn后面跟进程名称。在我的使用过程中,win7的系统,用adplus抓取w3wp进程老失败,抓其他普通进程没问题,最终我用windows任务管理器查看到的进程界面,点击w3wp进程,右键创建转储文件,它自动生成的dmp的dump文件到临时目录,这里它创建的dump文件大小将远远大于当前进程的实际大小。

我的测试程序在VS2010下的MVC2代码如下:模拟常见的程序造成循环过大,静态事件绑定到实例对象,造成不释放内存等会引起CPU过大,内存过高的问题。


 1     public class HomeController : Controller
 2     {
 3         public static event EventHandler MyEvent;
 4         List<byte[]> list = new List<byte[]>();
 5         public ActionResult Index()
 6         {
 7             ViewData["Message"] = "欢迎使用 ASP.NET MVC!";
 8 
 9             MyEvent += new EventHandler(TestEvent);
10             MyEvent(null, new EventArgs());
11             MyMethod();
12 
13             return View();
14         }
15 
16         public void MyMethod()
17         {
18             long i = 0;
19             while (i < 999000000)
20             {
21                 i++;
22             }
23         }
24 
25         public void TestEvent(object obj, EventArgs args)
26         {
27             for (int i = 0; i < 20; i++)
28             {
29                 list.Add(new byte[1024 * 1024 * 10]);
30             }
31         }
32     }

访问/home/index后,造成我CPU马上升到50%左右,内存倒看不出来,但多个访问后会有无法释放的内存越来越大。

首先载入sos后,下面是我的命令记录:(.........为省略更多内容,由于我记录的时候线程已经切换到25了,显示0:025>了)

0:025> !threadpool
CPU utilization: 51%

...................

查看什么线程占用CPU多一点

0:025> !runaway
 User Mode Time
  Thread       Time
  25:920       0 days 0:00:03.042
   0:150c      0 days 0:00:00.046
   9:6c        0 days 0:00:00.015
  27:1598      0 days 0:00:00.000
  26:15cc      0 days 0:00:00.000
  24:1084      0 days 0:00:00.000

切换到25线程:

0:025> ~25s
eax=2362d4fc ebx=00000000 ecx=00000001 edx=00000000 esi=01c9e838 edi=01ca4934
eip=00d70746 esp=0e2dee44 ebp=0e2dee58 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
00d70746 8bd9            mov     ebx,ecx

查看托管代码:

0:025> !clrstack
OS Thread Id: 0x920 (25)
Child SP IP       Call Site
0e2dee44 00d70746 DumpWebTests.Controllers.HomeController.MyMethod()
0e2dee60 00d70580 DumpWebTests.Controllers.HomeController.Index()

...............................

0:025> !name2ee * DumpWebTests.Controllers.HomeController
Module:      64bd1000
Assembly:    SMDiagnostics.dll

................

Module:      008b689c
Assembly:    DumpWebTests.dll
Token:       02000004
MethodTable: 0130002c
EEClass:     00c84348
Name:        DumpWebTests.Controllers.HomeController

查看模块信息:

0:025> !dumpmt 0130002c
EEClass:      00c84348
Module:       008b689c
Name:         DumpWebTests.Controllers.HomeController
mdToken:      02000004
File:         C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\root\9f8ccc72\b9d96a8\assembly\dl3\9b2cfeec\916cd56e_eebacb01\DumpWebTests.dll
BaseSize:        0x38
ComponentSize:   0x0
Slots in VTable: 45
Number of IFaces in IFaceMap: 6

查看所有程序集:

0:025> !dumpdomain

查看到下面的信息:

Module Name
008b689c            C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\root\9f8ccc72\b9d96a8\assembly\dl3\9b2cfeec\916cd56e_eebacb01\DumpWebTests.dll

Assembly:           00e4b2c8 [C:\Windows\assembly\GAC_MSIL\System.Web.Mvc\2.0.0.0__31bf3856ad364e35\System.Web.Mvc.dll]
ClassLoader:        00e234f8
SecurityDescriptor: 00e82280

保存程序集:

0:025> !savemodule 008b689c d:\dump\out.dll
3 sections in file
section 0 - VA=2000, VASize=39c4, FileAddr=200, FileSize=3a00
section 1 - VA=6000, VASize=320, FileAddr=3c00, FileSize=400
section 2 - VA=8000, VASize=c, FileAddr=4000, FileSize=200

已经把分析出的有问题的程序dll保存到d盘dump目录的Out.dll文件了,如果有源代码,当然可以直接查看对应方法的代码,这个就把CPU过高的程序找到了,具体原因当然还要自己分析代码了,

分析内存过高的方法,前面的常用方法里按照步骤就能找到了,这里就不写到博文里了。

其实我也还对windbg+sos调试代码的方式比较陌生,还不够熟悉,但是还是像最开始说的,只要稍微比较熟悉了,连蒙带差还是能大体找到处问题的地方,精确找到问题,还是需要进一步的学习。

本篇文章中,也许有不对的地方,如果发现,请指正,防止自己和大家以后出现同样的问题:)

用windbg+sos找出程序中谁占用内存过高,谁占用CPU过高(转载)的更多相关文章

  1. 使用ps、top、ps_mem命令找出Linux中的最大内存消耗过程

    使用ps.top.ps_mem命令找出Linux中的最大内存消耗过程 2020-02-08 16:06:59作者:自力稿源:云网牛站 您可能已经看到Linux系统多次消耗过多的内存,如果是这种情况,那 ...

  2. 找出程序GasMileage中的哪一行与下列叙述相对应:

    找出程序GasMileage中的哪一行与下列叙述相对应: a.通知程序将使用Scanner类   import java.util.Scannner; b.创建一个Scanner类的对象   Scan ...

  3. 找出数组中出现次数超过一半的数,现在有一个数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数

    找出数组中出现次数超过一半的数,现在有一个数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数 #include<iostream>using namespace s ...

  4. 阅读OReilly.Web.Scraping.with.Python.2015.6笔记---找出网页中所有的href

    阅读OReilly.Web.Scraping.with.Python.2015.6笔记---找出网页中所有的href 1.查找以<a>开头的所有文本,然后判断href是否在<a> ...

  5. 通过Web安全工具Burp suite找出网站中的XSS漏洞实战(二)

    一.背景 笔者6月份在慕课网录制视频教程XSS跨站漏洞 加强Web安全,里面需要讲到很多实战案例,在漏洞挖掘案例中分为了手工挖掘.工具挖掘.代码审计三部分内容,手工挖掘篇参考地址为快速找出网站中可能存 ...

  6. [LeetCode] Find All Numbers Disappeared in an Array 找出数组中所有消失的数字

    Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and ot ...

  7. 剑指Offer 找出字符串中第一个只出现一次的字符

    题目描述 找出字符串中第一个只出现一次的字符 如果无此字符 请输出'.' 输入描述: 输入一串字符,由小写字母组成 输出描述: 输出一个字符 输入例子: asdfasdfo 输出例子: o 思路:数组 ...

  8. 找出字符串中第一个不重复的字符(JavaScript实现)

    如题~ 此算法仅供参考,小菜基本不懂高深的算法,只能用最朴实的思想去表达. //找出字符串中第一个不重复的字符 // firstUniqueChar("vdctdvc"); --& ...

  9. 剑指Offer:找出数组中出现次数超过一半的元素

    题目:找出数组中出现次数超过一半的元素 解法:每次删除数组中两个不同的元素,删除后,要查找的那个元素的个数仍然超过删除后的元素总数的一半 #include <stdio.h> int ha ...

随机推荐

  1. [CareerCup] 13.4 Depp Copy and Shallow Copy 深拷贝和浅拷贝

    13.4 What is the difference between deep copy and shallow copy? Explain how you would use each. 这道题问 ...

  2. BASE64Decoder 编码(sun.jar)

    Base64 是网络上最常见的用于传输8Bit 字节代码的编码方式之一,大家可以查看RFC2045 -RFC2049 ,上面有MIME 的详细规范.  Base64 要求把每三个8Bit 的字节转换为

  3. 第八章 self sizing cell

    本项目是<beginning iOS8 programming with swift>中的项目学习笔记==>全部笔记目录 ------------------------------ ...

  4. Github上Python开发者应该关心的Repo

    carbaugh/lice lice : Generate license files for your projects 一个用来为你的项目生成许可证的工具.这下可方便了,不用手工的去修改了! co ...

  5. JS的十大经典算法排序

    引子 有句话怎么说来着: 雷锋推倒雷峰塔,Java implements JavaScript. 当年,想凭借抱Java大腿火一把而不惜把自己名字给改了的JavaScript(原名LiveScript ...

  6. setter方法的内存错误

    - (void)setList:(ClassicList *)list { self.list = list; _titleLabel.text = list.activityName; _addre ...

  7. 每天一个linux命令(34):kill命令

    Linux 中的kill命令用来终止指定的进程(terminate a process)的运行,是Linux下进程管理的常用命令.通常,终止一个前台进程可以 使用Ctrl+C键,但是,对于一个后台进程 ...

  8. 完美实现开机启动虚拟WIFI,顺便实现目前的WP8系统使用VPN(7.1修)

    众所周知,windows7系统的机器若带有无线网卡(台式机可以买一个USB无线网卡,京东目前39元,TP-Link的),可以虚拟出wifi,供手机等移动设备使用. 虚拟的WIFI的命了和软件在网上都找 ...

  9. Ibatis中传List参数

    Ibatis中用list传参数的方式. Java代码  select count(id) from `user` where id in #[]# and status=1 . <select ...

  10. SSH框架总结(框架分析+环境搭建+实例源码下载)

    来源于: http://blog.csdn.net/shan9liang/article/details/8803989 首先,SSH不是一个框架,而是多个框架(struts+spring+hiber ...