zoukankan      html  css  js  c++  java
  • 用windbg+sos找出程序中谁占用内存过高,谁占用CPU过高

    很早看到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(nullnew 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调试代码的方式比较陌生,还不够熟悉,但是还是像最开始说的,只要稍微比较熟悉了,连蒙带差还是能大体找到处问题的地方,精确找到问题,还是需要进一步的学习。

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

  • 相关阅读:
    [Linux Sets] hosts, wlan and other net-rele
    [Source] 温柔的图片
    [CATARC_2017] 第三周 & 残四周
    [CATARC_2017] 第二周
    ubuntu 安装
    知规矩者混天下言。
    python+selenium的web自动化测试之二(Jenkins自动执行)
    python+selenium的web自动化测试之一(手工执行)
    Python 入门小实例笔记
    Web安全测试工具 Burp Suit 使用简介
  • 原文地址:https://www.cnblogs.com/Lawson/p/1942692.html
Copyright © 2011-2022 走看看