用windbg+sos找出程序中谁占用内存过高,谁占用CPU过高(转载)
原文地址:
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过高(转载)的更多相关文章
- 使用ps、top、ps_mem命令找出Linux中的最大内存消耗过程
使用ps.top.ps_mem命令找出Linux中的最大内存消耗过程 2020-02-08 16:06:59作者:自力稿源:云网牛站 您可能已经看到Linux系统多次消耗过多的内存,如果是这种情况,那 ...
- 找出程序GasMileage中的哪一行与下列叙述相对应:
找出程序GasMileage中的哪一行与下列叙述相对应: a.通知程序将使用Scanner类 import java.util.Scannner; b.创建一个Scanner类的对象 Scan ...
- 找出数组中出现次数超过一半的数,现在有一个数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数
找出数组中出现次数超过一半的数,现在有一个数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数 #include<iostream>using namespace s ...
- 阅读OReilly.Web.Scraping.with.Python.2015.6笔记---找出网页中所有的href
阅读OReilly.Web.Scraping.with.Python.2015.6笔记---找出网页中所有的href 1.查找以<a>开头的所有文本,然后判断href是否在<a> ...
- 通过Web安全工具Burp suite找出网站中的XSS漏洞实战(二)
一.背景 笔者6月份在慕课网录制视频教程XSS跨站漏洞 加强Web安全,里面需要讲到很多实战案例,在漏洞挖掘案例中分为了手工挖掘.工具挖掘.代码审计三部分内容,手工挖掘篇参考地址为快速找出网站中可能存 ...
- [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 ...
- 剑指Offer 找出字符串中第一个只出现一次的字符
题目描述 找出字符串中第一个只出现一次的字符 如果无此字符 请输出'.' 输入描述: 输入一串字符,由小写字母组成 输出描述: 输出一个字符 输入例子: asdfasdfo 输出例子: o 思路:数组 ...
- 找出字符串中第一个不重复的字符(JavaScript实现)
如题~ 此算法仅供参考,小菜基本不懂高深的算法,只能用最朴实的思想去表达. //找出字符串中第一个不重复的字符 // firstUniqueChar("vdctdvc"); --& ...
- 剑指Offer:找出数组中出现次数超过一半的元素
题目:找出数组中出现次数超过一半的元素 解法:每次删除数组中两个不同的元素,删除后,要查找的那个元素的个数仍然超过删除后的元素总数的一半 #include <stdio.h> int ha ...
随机推荐
- LINUX信息安全系统设计基础第一周学习总结
Linux系统简介 一.实验内容 了解 Linux 的历史,Linux 与 Windows 的区别等入门知识. 二.实验要求 阅读linux简介与历史 三.实验步骤 二.Linux 与 Window ...
- 获取iOS系统版本 --- UIDevice
UIDevice类是一个单例,其唯一的实例( [UIDevice currentDevice] ) 代表了当前使用的设备. 通过这个实例,可以获得设备的相关信息(包括系统名称,版本号,设备模式等等). ...
- 20145208《Java程序设计》第3周学习总结
20145208 <Java程序设计>第3周学习总结 教材学习内容总结 认识对象 类类型 在第三章的学习中,我了解到JAVA可区分为基本类型和类类型两种类型,在上周的学习中我学习了JAVA ...
- WebAPI2使用Autofac实现IOC属性注入完美解决方案
一.前言 只要你是.NETer你一定IOC,IOC里面你也会一定知道Autofac,上次说了在MVC5实现属性注入,今天实现在WebApi2实现属性注入,顺便说一下autofac的程序集的注入方式,都 ...
- 『开源』Slithice 2013 服务器集群 设计和源码
相关介绍文章: <『设计』Slithice 分布式架构设计-支持一体式开发,分布式发布> <『集群』001 Slithice 服务器集群 概述> <『集群』002 Sli ...
- android用欢迎界面加载运行环境
以前一直以为splash页只是图好玩.. 今天才知道是应该把环境加载放在这个页面... 论坛和github上太多仿XXX的项目果然只能学习下ui的思路... 以前把环境加载放在application里 ...
- 获取url据对路径写法
var _absUrl = (function () { var a; return function (url) { if (!a) a = document.createElement('a'); ...
- 一套简单可依赖的Javascript库
还是[百度]的产品——Tangram不是我偏心,百度不是我亲戚这东西看上去确实不错 Tangram是一套简单可依赖的Javascript库,主要分为Base和Component两部分.Base提供了开 ...
- 详解js中的闭包
前言 在js中,闭包是一个很重要又相当不容易完全理解的要点,网上关于讲解闭包的文章非常多,但是并不是非常容易读懂,在这里以<javascript高级程序设计>里面的理论为基础.用拆分的方式 ...
- Beta版本冲刺计划
1.下一阶段需要改进完善的功能 文件读取 界面 人员批量增改 数据库 ... 2.下一阶段新增的功能 人员权限分离分化. 课表导出 ... 3.需要改进的团队分工(针对之前的不足,需要加强和改进团队协 ...