Baal的专栏

魔力小宝蓝---IBM---I BELIEVE MONEY

用户操作
[即时聊天] [发私信] [加为好友]
baalID:soft_fair
57443次访问,排名2022,好友1人,关注者1人。
soft_fair的文章
原创 47 篇
翻译 4 篇
转载 61 篇
评论 8 篇
baal的公告
新势力海报网
新势力论坛
男人找乐子的网站
伟大的操作系统linux

Google


[ 新浪ViVi ] [ Poco网摘 ] [ 365KEY ] [ 博采 ] [ 亿友响享 ] [ 你摘 ] [ YouNote ] [ 天极网摘 ] [ 和讯网摘 ]

最近评论
frankrade:关注一下
lz有点不地道:http://blogs.msdn.com/tess/archive/2008/02/20/net-debugging-demos-lab-3-memory-review.aspx

原创翻译吗?原?!!!
钱先生:去 http://www.6128.cn/entry.htm 看看,,不过也是大部分打不开的,,
钱先生:文章不错,但是不难发现里面有些句子可能漏了些关键的词汇,苦了那些菜鸟。
haha:ok
文章分类
收藏
    相册
    SEO
    SEO(RSS)
    SEO探索
    好东西
    baal自己的东西
    google相关的一个blog
    微软官方安全摘要
    民兵的家园
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 dotnet产品调式-内存调试二收藏

    新一篇: dotnet产品调式-内存调试三 (使用WinDbg来调试用户模式下的dump文件) | 旧一篇: dotnet产品调式-内存调试一

     

    dotnet产品调式-内存调试二

    情景:内存耗费
    现在我们都了解了dotnet内存管理和垃圾收集的基本原理,让我看看asp.net应用程序是如何使用的。这些情景向我展示了如何去调式内存消耗的问题。你们也许已经知道,内存泄露并不是动态重新分配内存而导致的,重新动态分配内存不会导致内存泄露。一个很小的内存泄露可能不会被注意到,也可能仅导致一个很小的危害,但是大的内存泄露会通过消耗可用内存来导致严重行能问题。另外,还有一个内存有关的问题,它不是 “真的”内存泄露,但能体现出内存泄露的征兆。
    有一些典型的客户情景可能暗示内存问题:
    情景1 :一个电子商务网站出售产品,浏览的客户抱怨数据丢失,看见 “Server Application Unavailable”错误。他们不得不重新登陆,并不知道这是为什么。额外的,服务端性能 下降当内存使用增加的时候。
    情景2 :一个网站提供视频上传得服务,当有一个用户上传大文件时,服务器进程被回收,文件上传失败。
    处理这里问题的一个思路:
    当我们调试内存相关的问题时,我们有很多方法,下面的图展示了一个思路:
    流程图(处理内存耗费的问题)
    流程已经展示,现在让我们看看细节吧
    错误是指向内存泄露的征兆么?
    如果你使用iis,当查看应用程序事件日志,发现一个asp进程被回收,你看到这样一段类似的信息aspnet_wp.exe(PID:1234) 被回收,因为内存消耗超过~MB(~代表可用内存的百分比)
    注 在iis6中对应的进程是 w3wp.exe
    我的内存去哪里了?
    下一步是找到那一个进程使用了太多的内存。工具有:性能监视器 或者 任务管理器 能够指出这些进程。一旦你知道哪个进程有很大的嫌疑。你可以运行AutoDump+ (ADPlus)来创建一个w3wp.exe进程的内存dump文件,然后用WindDbg 调试工具和 SOS.dll 调试扩展来检查托管和本地内存。这个随后讨论。
    本地内存耗费
    当使用性能监视器,如果 “Private Bytes ”计数器和“ .NET # of Bytes in all Heaps ”计数器以相同的比率在增加。这是一个证明是托管内存消耗的证据。看看已经分配内存的大小,思考GC正在干什么。当查看dump文件的时候,使用SOS命令来列出托管堆的大小,和这个dump 文件的大小比较一下,看看什么细节你能学到从有关大对象堆(LOH)和代(Generations)的知识中。查看一下是不是大对象(85K或更大)或小对象消耗了大部分的内存。如果是前者,查看有关LOH的一些细节,如果是后者,考虑第0代(G0)、第1代(G1)、第2代(G2)中包含什么。对于大对象,看看是否被根化(rooted),是否需要根化(rooted),如果他们没有被根化,他们就是下一个被回收的目标,确认最终它们是不是被合理的回收了。
    使用WinDbg 和SOS.dll 来查看所有这些很多的小对象的细节是比价困难的。在这种情况下,使用 CLR Profiler 这个工具来查看细节会比较方便。这个工具查看大对象也是可以的。
    本章节将使用这些工具。
    内过消耗过程
    下面的一个场景是经过简化的,最真实的一个描述。一个ASP.NET应用程序分配了太多的内存并且被回收了,因为它超过了在进程模型中的内存限制。下面的内容是阐明这种调试技术可以帮助你来定位一个问题,生产应用的环境可能不像这里这样简单清晰,但是你可以使用类似的这种技术来定位内存消耗的问题。这个例子中申请了一个大内存,通过消耗可用内存足以导致严重的性能问题,这个例子中asp.net 页面申请了大对象(20M每次),然后把它们缓存在asp.net 的cache中。缺省情况下,当内存消耗达到60%,asp.net进程就会被回收,下面讲述的内容的目的是找出原因。
    首先,你可以按如下步骤来做:
    1) 从浏览器中查看http://localhost/debugging/memory.aspx 并看页面上的表中的初始数据。
    2) 按照上面的流程图中的步骤来找到错误,你可以从页面反馈的信息和应用程序事件查看器中去找。
    3) 创建一个dump文件,然后寻找里面的一些数据信息,工具可以使用WinDbg 和SOS.dll.
    4) 检查针对这个asp.net 进程的托管内存,并找到是什么对象消耗了大部分的内存。
    5) 当你从dump文件中找到一些证据和蛛丝马迹后,去查看源代码。
    以上的步骤可以锻炼你的查找定位能力。
    下面请跟着我的思路
    预备环境
    首先,收集一些初始的数据,工程文件、安装程序都可以下载。
    查看 Memory.aspx页面,从浏览器中查看http://localhost/debugging/memory.aspx,注意那些页面中的表格里面显示的信息。如下图:
     
    表格中几个字段的意义是:

    字段
    含义
    StartTime
    Aspnet_wp.exe/w3wp.exe 进程开始的时间
    Age
    该进程运行的总时间长度
    ProcessID
    该进程的id编号
    RequestCount
    完成的请求的数目,初始化是0
    Status
    该进程的当前状态,
    Alive:进程正在运行。
    Shutting Down:进程正在关闭
    ShutDown:进程已经关闭,正常关闭
    Terminated:异常关闭,
    ShutdownReason
    进程关闭的袁鹰:
    Unexpected: 意外关闭,非希望的关系。
    Requests Limit:进程执行该请求超出了限制
    Request Queue Limit:处理该请求的进程超出了队列数目的限制
    TimeOut:进程重新启动,因为超时。
    Memory Limit Exceeded:进程超过内存限制
    PeakMemoryUsed
    最大内存使用量,这个值对应性能监视器中的Private Bytes (maximum amount) 计数器
     

    你应该已经研究过源代码了。
    每次,点击 “Allocate 20M Objects”按钮,五个缓存对象(缓存key 也是唯一的)被放到System.Web.Cache中,“Allocate 200K Objects”按钮的工作方式也是差不多,但它每次是创建200 k 的对象,这个按钮的目的是在试验中模拟非致命的泄漏,可以和20M 的交换测试。
    “Free Memory”按钮在当前会话范围内有一个缓存key的列表,能够清楚缓存,它调用System.GC.Collect() 方法来强制垃圾收集。这里需要注意,System.GC.Collect() 方法仅仅是为了示范的目的,并不是推荐我们在实际中这样使用,显式的调用System.GC.Collect() 会改变GC自动收集的特性,不断地调用System.GC.Collect() 会刮起所有的线程直道垃圾收集结束,这会大大降低性能。
    “Refresh Stats”按钮可以刷新内存统计数据。
    你可以使用任务管理器和性能监视器来查看到更多的有关信息。
    打开任务管理器,在“进程”选项卡上,点击“查看”菜单,点击“选择列”然后把“虚拟内促页大小(Virtual Memory Size)”这个给勾上。如果你是在服务器上,远程的控制,你要把 “显示所有用户进程(Show processes from all users)”这个也勾上。
    读出这个虚拟内存的数据,这个值是9,820 KB,还是比较合理的。

    Process
    Virtual memory size
    Aspnet_wp.exe
    9,820 KB

     
    打开性能监视器。
    1)在“控制面板”中,打开“管理工具(Administrative Tools)”,双击 “性能(Performance)”
    在性能管理器工具栏上 点击“+”打开“添加计数器”对话框,从“性能对象(Performance object)”的下拉框中选择“.NET CLR Memory”。
    2)在“从列表选择实例”中选中“w3wp.exe”。
    3)把下图中所列出的计数器全部选上。重复上面的步骤把“ASP.NET Applications”和“Process”两个性能对象也添加进来,计数器也添加进来。
    4)点击工具栏上的“查看报告”按钮,从图表转换到文本模式
     
    在监视器中特别关注 # Bytes in all Heaps, Large Object Heap Size, Cache API Entries.
    # Bytes in all Heaps 代表这 Gen 0 Heap Size, Gen 1 Heap Size, Gen 2 Heap Size, 和 Large Object Heap Size的大小的总和,指示当前内存中分配的GC堆的大小,以 字节为单位。
    Large Object Heap Size 代表大对象堆的大小,以字节为单位,该计数器在垃圾收集完后才会改变计数,并不是每次分配都会刷新计数。
    Cache API Entries代表在应用程序缓存(cache)中的实体的总个数。
    当前大小是:
    Large Object Heap Size: 22,608 bytes
    # Bytes in all Heaps: 2,589,252
    Cache API Entries: 0
     
    有关计数器的更多信息可以查看
    ".NET Framework General Reference: Memory Performance Counters" on the MSDN Web site at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/gngrfmemoryperformancecounters.asp.
    ".NET Framework Developer's Guide: Performance Counters for ASP.NET" on the MSDN Web site at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconperformancecountersforaspnet.asp.
     
     
     
    第一次分配过程
    现在你已经有了应用程序、性能监视器的原始数据,看看本地和托管的内存消耗吧,点击“Allocate 20 MB Objects”按钮一次,你得到的数据将和下面表格中的类似:

    Field
    Baseline value
    New value
    StartTime
    07/08/2002 12:14:06 PM
    07/08/2002 12:40:59 PM
    Age
    00:00:04.2961776
    00:00:33:9585520
    ProcessID
    3,212
    3,212
    RequestCount
    0
    1
    Status
    Alive
    Alive
    ShutdownReason
    N/A
    N/A
    PeakMemory Used
    5,948
    8,904
    Updated Memory Stats
    Baseline value
    New value
    GC.TotalMemory
    780 KB
    100,912 KB
    Private Bytes
    8,896 KB
    117,616 KB

    下面出现了一个新的表格:
    GC.TotalMemory表示总的托管内存数目。该值对应性能监视器中的# Bytes in all Heaps(该计数器 位于  .NET CLR Memory Performanc对象中)e
    Private Bytes 是总的进程本地内存数目,它是不能与其他进程共享的内存。
    你可以看到,RequestCount 变成了1 ,GC.TotalMemory Private Bytes 的值几乎都是100M。
    看看源代码:
    for (int i = 0; i< 5; i++)
    {
     long objSize = 20000000;
     string stime = DateTime.Now.Millisecond.ToString();
     string cachekey = "LOCache-" + i.ToString() + ":" + stime;
     Cache[cachekey] = CreateLargeObject(objSize);
     StoreCacheListInSession(cachekey);
    }
    Private Bytes 这个参数包含着进程的托管的和本地的内存。
    你也可以使用任务管理器来查看,切换到进程选项卡,看w3wp.exe这个进程你可以看到“虚拟内存使用量”也增加到了115,000KB 。

    Process
    Baseline value
    New value
    w3wp.exe
    9,820 KB
    114,840 KB

    虚拟内存已经增加了大约100MB,大部分都是asp.net 进程消耗的。
    注意任务管理器中的“虚拟内存使用量”和性能监视器中的Process: Private Bytes 相对应。
    在统计图中你看以看到Private Bytes# Bytes in all Heaps 的值在同时的增加,这表明增加的内存使用是发生在托管内存中,而不是本地内存。
    下图显示了内存增加的过程,
    你可以改变y轴的最大值来调整显示比例,在图表上右键,选择 “属性”,点击“图表”选项卡,然后找到并修改 Y 轴最大值。
    第二次点击分配
    这一步将分配更多的内存,再次点击“Allocate 20 MB Objects”,一共2次,下表显示了新的变化:

    Field
    Baseline value
    One allocation
    Two allocations
    StartTime
    07/08/2002 12:14:06 PM
    07/08/2002 12:40:59 PM
    07/08/2002 13:25:51 PM
    Age
    00:00:04.2961776
    00:00:23:9585520
    00:47:33.1343328
    ProcessID
    3,212
    3,212
    3,212
    RequestCount
    0
    1
    2
    Status
    Alive
    Alive
    Alive
    ShutdownReason
    N/A
    N/A
    N/A
    PeakMemory Used
    5,948
    8,904
    113,752
    Memory Stats
    Baseline value
    One allocation
    Two allocations
    GC.TotalMemory
    780 KB
    100,912 KB
    200,916 KB
    Private Bytes
    8,896 KB
    117,616 KB
    221,450 KB

    看看任务管理器中的变化:

    Process
    Baseline value
    One allocation
    Two allocations
    w3wp.exe
    9,820 KB
    114,840 KB
    216,240 KB

    “虚拟内存使用量”又增加了100M,大部分还是被asp.net 的进程消耗的。
    性能监视器的报告和图表也表达了这个意思。看看 “Cache API Entries”数目,和你在代码中看到的一样,每次点击事件中有一个循环,会创建5个缓存部件,运行了2次,那就是10个。
    #Bytes in all Heaps Large Object Heap Size的不同显示了大部分的托管内存被LOH使用了:
     
    第三次点击分配
    最后一次的点击耗费了更多的内存,快速的切换到任务管理器中的“性能”选项卡,检查“页面文件使用记录”(win200种是“内存使用量”)。
    每次点击“Allocate 20 MB Objects”按钮,图表显示有一个明显的斜度(增加趋势),并保持一定的水平直到下一次点击,如果这个进程被回收了,你可以看见一个明显的下降,下图显示了这个现象:
     
    任务管理器的这些现象可以让我猜测系统上的一些性能变化。你可以查看应用程序日志来确认发生了进程回收:
    Event Type:     Error
    Event Source:   ASP.NET 1.0.3705.0
    Event Category: None
    Event ID:       1001
    Date:           6/7/2002
    Time:           1:04:14 AM
    User:           N/A
    Computer:       machinename
    Description:     aspnet_wp.exe  (PID: 2740) was recycled because
                   memory consumption exceeded the 306 MB
                   (60 percent of available RAM).
     
    回到asp.net 的页面中,点击“Refresh Stats”按钮,你可以看见第二个表格被加入到页面中来,它包含了新进程的数据,进程健康监视器关闭了原先的进程,因为达到了内存限制值,然后启动了一个新进程。比较两个表格的数据,特别的,看看StatusShutdownReasonUpdated Memory Stat
    如果还有什么不清楚的,请重复以上的操作来增加认识。
     

    发表于 @ 2008年01月25日 12:39:00|评论(loading...)|编辑

    新一篇: dotnet产品调式-内存调试三 (使用WinDbg来调试用户模式下的dump文件) | 旧一篇: dotnet产品调式-内存调试一

    评论:没有评论。

    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © baal