使用Perfmon.exe调试分析内存不足(OutOfMemory)

32位操作系统的寻址空间是4G,其中有2G被操作系统占用,也就是说留给用户进程的内存只有2G(其中还要扣除程序加载时映像占用的部分空间,一般只有1.6G~1.8G左右可以使用)。

如果进程运行中需要申请内存,而操作系统无法为其分配内存空间,则会产生内存不足的异常,在.net中为System.OutOfMemoryException(The exception that is thrown when there is not enough memory tocontinue the execution of a program.)。

虽然最终的表现都为OutOfMemoryException,但其产生的原因可能是不一样的,动手解决此问题之前需要先对进程当前内存的使用状态进行分析,找出正确的原因,才能对症下药。下面分享一下调试此类问题的一些心得。

一、使用Perfmon.exe

1)   命令行输入perfmon.exe。打开“性能”。

2)   在“性能日志与警报-计数器日志”上右键,选择“新建日志设置”。

3)   输入日志名称,如“OOM”。

4)   在“常规-计数器”中删除所有默认的计数器(如果有)。

5)   点击“添加计数器”,性能对象选择“.NET CLR Memory”,计数器选择并添加“Bytes in all heaps”、“Large Object Heap Size”。同样“性能对象”选择“Process”,计数器选择并添加“Virtual bytes”、”Private bytes”。注意点击“添加”前需要在“从列表选择范例”选择框选择需要监控的进程。

另外,如果当前系统登陆的用例对目标进程没有调试权限,需要在“运行方式”框里填入domain\username,并输入密码。

6)   数据采样间隔可以设置小一点,如1秒钟。

7)   点击“确定“,新的计数器日志就新建成功了。右边的框框中可以看到新的计数器,绿色表示正在运行中。”“日志文件名“列显示了本次监控结果将写入的日志文件名(同一个计数器运行多次,写入的日志文件名是不同的)。

8)   让程序与计数器运行一段时间,然后停止计数器(为什么要停止计数器?我的机器上测试的时候,需要先停止计数器后,才会把监控的结果写到日志文件中,如果不先停止,在下面的监视器中将看不到计数器运行这段时间的监控结果。)。

9)   点击“系统监视器“。点击”“查看日志数据”(图标为)按钮,在“来源”选项卡里添加日志文件为刚刚我们新建的计数器产生的日志文件。下方可选择时间范围,这里选全部即可。然后在“数据”选项卡里添加需要查看的计数器(此选择卡还可以定义不同的计数器显示的样式及显示比例)。

10) 从图上可以看到在计数器运行的时间段中,被监控进程的内存使用情况。在添加计数器的窗口中有对相应计数器的简单说明,下面是几个常用的计数器:

·           Bytes in all Heaps:.net托管堆(GC)使用的总内存。包括0代、1代、2代及大对象堆。

·           Large Object Heap size:大对象堆使用的内存。.net在分配内存时大于85K的对象会被放到这个堆中,不同于0、1、2代,大对象堆中的内存不是连续的,在垃圾回收时也不会移动大对象的地址(我系统显示为大于20K对象为大对象,实际上2.0应该为大于85K)。

·           Private bytes:该计数器记录了当前通过VirtualAlloc API Commit的Memory数量。无论是直接调用API申请的内存,被Heap Manager申请的内存,或者是CLR 的managed heap,都算在里面。跟Handle Count一样,如果在整个程序周期内总体趋势是连续向上,说明有MemoryLeak(摘自百度)。

·           Virtual bytes:该计数器记录了当前进程申请成功的用户态总内存地址,包括DLL/EXE占用的地址和通过VirtualAlloc API Reserve的Memory Space数量,所以该计数器应该总大于Private Bytes。一般来说,Virtual Bytes跟Private Bytes的变化大致一致。由于内存分片的存在, Virtual Bytes跟Private Byes一般保持一个相对稳定的比例关系。当Virtual Bytes跟Private Bytes的比例关系大于2的时候,程序往往有比较严重的内存地址分片(摘自百度,但对.net程序来说一般差别在200M以下还算是正常的)。

11) 有了上面几个计数器的结果之后,一般可以通过以下规则大致定位问题的所在:

·           Virtual bytes增长但Private bytes没有显著增长。为Virtual bytes泄露。

·           Private bytes增长但bytes in all heaps没有显著增长。为非托管资源泄露,检查有没有COM组件或其它非托管调用没有正确释放内存。

·           Bytes in all heaps显著增长。为.net托管内存泄露。由于.net内存是GC管理的,自动回收,这里有可能是缓存了过多的数据,或程序中引用混乱导致本来需要被回收的数据还被其它对象所引用从而GC没法回收这部分数据。

·           Bytes in all heaps有增长但使用不多,系统剩余可用内存也比较多(需要再添加相应的计数器)。这种情况比较少见,但我遇到过一次是由于非托管在存在大量碎片,导致.net在申请大对象时失败。

原文:https://blog.csdn.net/lazyleland/article/details/6704661

原文地址:https://www.cnblogs.com/cn2018/p/10655827.html

时间: 2024-11-10 08:37:11

使用Perfmon.exe调试分析内存不足(OutOfMemory)的相关文章

内存不足(OutOfMemory)的调试分析

32位操作系统的寻址空间是4G,其中有2G被操作系统占用,也就是说留给用户进程的内存只有2G(其中还要扣除程序加载时映像占用的部分空间,一般只有1.6G~1.8G左右可以使用). 如果进程运行中需要申请内存,而操作系统无法为其分配内存空间,则会产生内存不足的异常,在.net中为System.OutOfMemoryException(The exception that is thrown when there is not enough memory tocontinue the executi

分析内存泄露问题

转自:http://rayleeya.iteye.com/blog/1956638 无论怎么小心,想完全避免 bad code 是不可能的,此时就需要一些工具来帮助我们检查代码中是否存在会造成内存泄漏的地方. 既然要排查的是内存问题,自然需要与内存相关的工具,DDMS和MAT就是两个非常好的工具.下面详细介绍. 2.3.1 内存监测工具 DDMS --> Heap Android tools 中的 DDMS 就带有一个很不错的内存监测工具 Heap(这里我使用 eclipse 的 ADT 插件,

程序员突围-程序调试分析(一) 我从菜鸟进化的感悟

程序员突围-程序调试分析(一) 我从菜鸟进化的感悟 在说程序调试分析之前,我们还是了解一些基本的概念性的东西(在下现在从事java,因而都已java为例) 1. bug的分类 根据程序的阶段和MSDN和看过的一些书籍的分析,bug分为编译错误,运行时错误和逻辑的错误 (1)  编译错误 一般初学者犯错比较多的地方,编译错误,说白了就是程序在从java编译成.class文件时出现了问题,这个问题的现象比较明显,比如说语句写的有问题,那么对于这类问题的解决方法是什么呢,翻翻书,翻翻API(翻阅API

Android 中如何分析内存泄漏

前提条件: 1,电脑安装了java 运行环境 2,手机端开启了 USB 调试开关 3,获取 root 权限 4,安装MAT工具,下载地址:http://www.eclipse.org/mat/downloads.php 基本步骤: 1,使用eclipse 自带的 DDMS 工具分析各线程的内存使用情况,如下图所示 Heap视图界面会定时刷新,在对应用的不断的操作过程中就可以看到内存使用的变化. 怎样判断当前进程是否有内存泄漏呢? 这里需要注意一个值:VM Heap页面中部有一个data obje

【转】node.exe调试JavaScript代码

node.exe调试JavaScript代码 目的: Console.log可以打印一些信息,光有log还不够,当程序出现问题时通过log可以定位到错误位置,但是当我们想查看错误现场的变量时,log就无能为力了,一般情况下我们不会把所有的变量都打印出来.此时就需要断点的功能了,在程序里边打上断点,直接定位到错误位置,分析错误现场确认错误原因. 三种模式: nodejs内部提供一个debug机制,可以让程序进入debug模式,供开发者一步一步分析代码发现问题. 共有3中启动参数可以让程序进入deb

jQuery之ajax错误调试分析

jQuery之ajax错误调试分析 jQuery中把ajax封装得非常好.但是日常开发中,我偶尔还是会遇到ajax报错.这里简单分析一下ajax报错 一般的jQuery用法如下,ajax通过post方式提交"汤姆和老鼠"这段数据到xxx.php文件中.成功后则打印返回的数据,失败则打印错误原因. 1 2 3 4 5 6 7 8 9 10 $.ajax({     url:"xxx.php",     type:"post",     dataty

使用Android Studio分析内存问题

大家好!本人是即将毕业学生一枚,闲暇时间经常看大神们写的博客学到很多东西.最近在做毕业设计的时候遇到一些问题,然后把自己的问题和解决方法总结一下,有不对的地方希望大家多多包涵,提出批评与指导. 这篇博文主要介绍使用AndroidStudio对内存进行分析和跟踪,还有就是从源码角度解决ImageLoader引起的OOM问题. 我正在做的项目使用到了ImageLoader来加载图片,我也是第一次使用,就拿来直接用了.写完的代码运行很正常的加载图片,并没有发现什么问题.但是在测试的时候发现了问题.当多

Android最佳性能实践(二)——分析内存的使用情况

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/42238633 虽说现在的手机内存都已经非常大了,但是我们大家都知道,系统是不可能将所有的内存都分配给我们的应用程序的.没错,每个程序都会有可使用的内存上限,这被称为堆大小(Heap Size).不同的手机,堆大小也不尽相同,随着现在硬件设备不断提高,堆大小也已经由Nexus One时的32MB,变成了Nexus 5时的192MB.如果大家想要知道自己手机的堆大小是多少,可以调用如

程序员突围-程序调试分析(序)

-从实践到思考,痛苦的煎熬 其实算算,工作一年了,从大学毕业至今,接触编程已经五年了,但是真正的编程感觉还没有开始,从大一开始接触C语言,陆续接触c++,java,C#等等,现在感悟到了一点,编程语言学那么多有什么用呢?其实把一门编程语言学精了,学透了,其他的是触类旁通的(底层的C语言和C++可能有点例外),下面我会说一下我的经历,我感觉可能是大多数学习编程人的必经的阶段,让大家对编程的抵触少一些,然后想想一个我这样的白痴都能慢慢的开始程序调试,程序分析,你们绝对比我强的,下篇文章才会进入我的程