.net 框架号称永远不会发生内存泄漏,原因是其引入了内存回收的机制。但实际应用中,往往我们分配了对象但没有释放指向该对象的引用,导致对象永远无法释放。最 常见的情况就是给对象添加了事件处理函数,但当不再使用该对象时却没有将该函数从对象的事件handler中减掉。另外如果分配了非托管内存,而没有手工 释放,GC同样无能为力。所以当.net应用发生内存泄漏后如何跟踪应用的内存使用情况,定位到程序设计中的缺陷显得非常重要。本文将介绍通过.NET Memory Profiler来跟踪.net应用的内存泄漏,为定位.net应用内存问题提供一个解决途径。

.NET Memory Profiler是一款强大的.net 内存跟踪和优化工具。该工具目前可以对一下4种.net应用进行内存跟踪。

  • 基本应用 例如winform, console application等
  • ASP.net 应用
  • WPF应用
  • Window 服务

本篇将通过对以下三种内存的跟踪来阐述如何使用该工具对基本.net应用程序进行内存的跟踪。三种内存包括:

  • 托管内存
  • 线程托管内存
  • 非托管内存

在开始之前,先需要建立环境。
       我采用.NET Memory Profiler V3.1.307 版本进行测试。安装完后需要新建一个项目,由于我们需要测
.net基本应用,所以新建项目时选择Standalone application. 点击next后,输入要测试的.net 应用的路径和参数。
然后按下 finish.项目就建立完成了。

测试程序是我编写的,编译后生成TestMemorySize.exe 这个控制台应用程序。下载地址

代码如下

主程序等待用户输入,输入m,t,u 分别是增加托管内存,创建一个自动增加托管内存的线程,增加非托管内存。
输入d,释放主线程创建的托管内存对象。


using System;

using System.Collections.Generic;

using System.Text;

namespace TestMemorySize

{

    class Program

    {

        static void Main(string[] args)

        {

            MemoryInc memoryInc = new MemoryInc();

            while (true)

            {

                long memorysize = System.Diagnostics.Process.GetCurrentProcess().PagedMemorySize64;

                Console.WriteLine(string.Format("PagedMemorySize:{0}MB", memorysize / (*)));

                Console.WriteLine(string.Format("ManagedMemIncTimes:{0}", memoryInc.ManagedMemIncTimes));

                Console.WriteLine(string.Format("UnmanagedMemIncTimes:{0}", memoryInc.UnmanagedMemIncTimes));

                String cmd = Console.ReadLine();

                switch (cmd)

                {

                    case "d":

                        memoryInc = new MemoryInc();

                        GC.Collect();

                        break;

                    case "m":

                        memoryInc.IncManagedMemory();

                        break;

                    case "u":

                        memoryInc.IncUnmanagedMemory();

                        break;

                    case "t":

                        MemoryLeakThread thread = new MemoryLeakThread();

                        break;

                    case "l":

                        break;

                }

            }

        }

    }

}

MemoryInc 是一个增加托管内存和非托管内存的类。


using System;

using System.Collections.Generic;

using System.Text;

using System.Runtime.InteropServices;

namespace TestMemorySize

{

    class MemoryInc

    {

        int _ManagedMemIncTimes = ;

        int _UnmanagedMemIncTimes = ;

        List<byte[]> _ManagedMemory = new List<byte[]>();

        LinkedList<IntPtr> _UnmanagedMemory = new LinkedList<IntPtr>();

        /// <summary>

        /// Managed memory increase times

        /// </summary>

        public int ManagedMemIncTimes

        {

            get

            {

                return _ManagedMemIncTimes;

            }

        }

        /// <summary>

        /// Unmanaged memory increase times

        /// </summary>

        public int UnmanagedMemIncTimes

        {

            get

            {

                return _UnmanagedMemIncTimes;

            }

        }

        /// <summary>

        /// Increase managed memory

        /// </summary>

        public void IncManagedMemory()

        {

            _ManagedMemIncTimes++;

            _ManagedMemory.Add(new byte[ *  * _ManagedMemIncTimes]);

        }

        /// <summary>

        /// Increase unmanaged memory

        /// </summary>

        public void IncUnmanagedMemory()

        {

            _UnmanagedMemIncTimes++;

            _UnmanagedMemory.AddLast(Marshal.AllocCoTaskMem( *  * _UnmanagedMemIncTimes));

        }

    }

}

MemoryLeakThread 这个线程没30秒增加1M的托管内存占用。

MemoryLeakThread

准备就绪,下面就开始体验了。

1、托管内存的跟踪
       菜单中选择Profiler->Start 启动TestMemorySize.exe,然后输入m 并回车,这是分配了1M的托管内存。
在菜单中选择Profiler->Collect Heap Shapshot. 这是就可以看到堆中的所有对象了。

从这个界面我们看到虽然列出了对象的列表,但只有类型和大小等信息,却没有对象的名称以及分配过程
信息,这样怎么定位那块内存没有被释放啊?不要着急,.NET Memory Profiler还是比较强大的,让我们继续往下
前进。

双击选中的对象后进入对象所占用的堆的详细信息

再双击选中行,这时我们就可以看到对象的名称和分配堆栈的情况了。是不是很兴奋?终于找到是哪个家伙在捣蛋了。

2、线程中创建的托管内存的跟踪
       线程中创建的托管内存跟踪方法和第1节介绍的方法基本是一样的。启动TestMemorySize.exe后输入t 并回车,创建一个
吃内存的线程。下面步骤都相同了。

3、非托管内存的跟踪
       要跟踪非托管内存需要做一个设置:选择菜单中view->Project Property Pages,按下图进行设置。

设置好后启动TestMemorySize.exe后输入u 并回车,创建1M的非托管内存。下面步骤相同。

非托管内存无法看到对象的名称,但可以看到内存的申请过程,这对于定位内存问题已经提供了很大的帮助。

现在我们再输入m 回车,创建1M的托管内存,然后输入d 回车,这时我们可以发现memoryInc对象申请的托管内存已经被释放掉,
但非托管内存依然存在,内存在这里泄漏了!

这个工具还可以帮助我们计算出托管对象在堆中实际占用的内存大小,这也是一个很实用的功能,我们可以发现实际的占用大小
要比我们设计的大小略大,这是因为我们设计的类及其成员都是从一些基类中继承,这些基类的数据占用了一些内存造成。

到此如何跟踪基本.net应用的内存问题就介绍完毕。有时间再谢谢怎么跟踪ASP.NET应用的内存问题。
这一篇本来上午就要发出来,都快写完了,IE 崩溃!抓狂!

下午又重新写了一遍,郁闷啊。

用 .NET Memory Profiler 跟踪.net 应用内存使用情况--基本应用篇(转)的更多相关文章

  1. NET Memory Profiler 跟踪.net 应用内存

    NET Memory Profiler 跟踪.net 应用内存 用 .NET Memory Profiler 跟踪.net 应用内存使用情况--基本应用篇 作者:肖波      .net 框架号称永远 ...

  2. Net Memory Profiler 分析.Net程序内存泄露

    Net Memory Profiler 分析.Net程序内存泄露 Haozes's Tech Space 人類的全部才能無非是時間和耐心的混合物 使用.Net Memory Profiler 分析.N ...

  3. .NET Memory Profiler 查看内存使用情况

    1 简介 .Net Memory Profiler(以下简称Profiler):专门针对于.NET程序,功能最全的内存分析工具,最大的特点是具有内存动态分析(Automatic Memory Anal ...

  4. 使用ANTS Performance Profiler&ANTS Memory Profiler工具分析IIS进程内存和CPU占用过高问题

    一.前言 最近一段时间,网站经常出现两个问题: 1.内存占用率一点点增高,直到将服务器内存占满. 2.访问某个页面时,页面响应过慢,CPU居高不下. 初步判断内存一点点增多可能是因为有未释放的资源一直 ...

  5. [原创]推荐一款强大的.NET程序内存分析工具.NET Memory Profiler

    [原创]推荐一款强大的.NET程序内存分析工具.NET Memory Profiler 1 官方网站:http://memprofiler.com/2 下载地址:http://memprofiler. ...

  6. Windbg + .Net .NET Memory Profiler 排查内存泄露

    这是一个Winform程序,用于项目中的定时运算.症状是,运行一段时间后,内存持续上升.如一天内就能够达到300M. 打开.Net Memory Profiler,监控该程序,一段时间后,看到该程序产 ...

  7. (转).NET Memory Profiler 使用简介

    1         简介 .Net Memory Profiler(以下简称Profiler):专门针对于.NET程序,功能最全的内存分析工具,最大的特点是具有内存动态分析(Automatic Mem ...

  8. MVC+MEF+UnitOfWork+EF架构,网站速度慢的原因总结!(附加ANTS Memory Profiler简单用法)

    (最近使用内存分析工具ANTS Memory Profiler,以及其他网友提供的意见发现最终导致内存泄漏的就是MEF,在此特地更新下,与大家分享!最下面红色字体) 最近参考使用了郭明峰的一套架构来做 ...

  9. [转]ANTS Performance Profiler和ANTS Memory Profiler 使用

    .NET性能调优之一:ANTS Performance Profiler的使用   .NET性能调优系列文章 系列文章索引 .NET性能调优之一:ANTS Performance Profiler的使 ...

随机推荐

  1. BZOJ.2521.[SHOI2010]最小生成树(最小割ISAP/Dinic)

    题目链接 一条边不变其它边减少可以看做一条边增加其它边不变. 假设要加的边lab为(A->B,v),那么肯定是要使除这条边外,A->B的每条路径上的最小权值都\(>v\),这样在连通 ...

  2. Dos常用命令大全

    dos命令进入文件夹 输入 D: 回车,进入D盘的根目录,然后输入dir 回车 可以查看根目录下的文件和文件夹,  输入 cd空格文件夹的名字(不区分大小写) 进入文件夹根目录下, 依次输入dir 查 ...

  3. C#开发利器 Linq Pad 相关

    一,下载 Linq Pad 是平时在开发的过程中使用的利器,为什么这样说了. 你不用打开VS, 直接敲代码就行,F5运行即可以看到结果. 而且支持Linq, 是不错的选择. 最近想开发一个日志分析工具 ...

  4. spring boot学习总结(一)-- 基础入门 Hello,spring boot!

    写在最前 SpringBoot是伴随着Spring4.0诞生的: 从字面理解,Boot是引导的意思,因此SpringBoot帮助开发者快速搭建Spring框架: SpringBoot帮助开发者快速启动 ...

  5. mysql|表row_format的静态与动态,Compact

    innodb 一般对应 Compact  ,MyISAM 一般对应静态与动态 mysql中若一张表里面存在varchar.text以及其变形.blob以及其变形的字段的话,那么这个表其实也叫动态表,即 ...

  6. 企点微服务网关演进之路 IT大咖说 - 大咖干货,不再错过

      http://www.itdks.com/dakashuo/new/dakalive/detail/2297

  7. Overclock STM32F4 device up to 250MHz

    http://stm32f4-discovery.com/2014/11/overclock-stm32f4-device-up-to-250mhz/ Let’s test what STM32F4x ...

  8. Temporary ASP.Net Files探究

    了解.net平台的兄弟都知道,.net也是采用动态编译的也就是说我们常说的build生成的dll只是中间代码而在web第一次请求的时候才是真正意义上的编译生成二进制代码这也就是为什么刚编译完第一次打开 ...

  9. Lex与Yacc学习

    http://www.cnblogs.com/shine-yr/p/5214976.html

  10. Flex Viewer(二) 体系结构

    一.概述 在上一篇文章<深入浅出Flex Viewer (一)——概述>中,笔者对Flex Viewer用于构建以地图为中心的富客户端(RIA)应用的原型的功能和价值做了简要地介绍.在本文 ...