.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. ApiPost接口调试工具模拟Post上传文件(中文版Postman)

    ApiPost简介: ApiPost是一个支持团队协作,并可直接生成文档的API调试.管理工具.它支持模拟POST.GET.PUT等常见请求,是后台接口开发者或前端.接口测试人员不可多得的工具 . A ...

  2. 【并查集】BZOJ4551-[Tjoi2016&Heoi2016]树

    NOIP太可怕了((( -口-) 题目链接 [题目大意] 给定一颗有根树(根为1),有以下两种操作: 1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均无标记,而且对于某个结点 ...

  3. NOI.AC NOIP模拟赛 第四场 补记

    NOI.AC NOIP模拟赛 第四场 补记 子图 题目大意: 一张\(n(n\le5\times10^5)\)个点,\(m(m\le5\times10^5)\)条边的无向图.删去第\(i\)条边需要\ ...

  4. 吴恩达-coursera-机器学习-week7

    十二.支持向量机(Support Vector Machines) 12.1 优化目标 12.2 大边界的直观理解 12.3 数学背后的大边界分类(选修) 12.4 核函数1 12.5 核函数2 12 ...

  5. 2010-2011 ACM-ICPC, NEERC, Moscow Subregional Contest Problem I. Interest Targeting 模拟题

    Problem I. Interest Targeting 题目连接: http://codeforces.com/gym/100714 Description A unique display ad ...

  6. Windows 10官方原版ISO制作方法

    其实市面上的ISO原版都是这样的方法制作成光盘,然后再打包出来供人们下载的. 1.下载Windows 10安装程序工具: https://www.microsoft.com/zh-cn/softwar ...

  7. Android学习笔记PreferenceFragment的使用

    相信大家对Perference都比较熟悉了,也就是我们常说的偏好设置,首选项设置,可以保存一些数据,例如我们在上一次使用的时候的一些内容,希望在下一次启动后依然生效,而不需要再进行配置那么麻烦.一般这 ...

  8. LightOJ 1118 - Incredible Molecules (两圆面积交)

    1118 - Incredible Molecules   PDF (English) Statistics Forum Time Limit: 0.5 second(s) Memory Limit: ...

  9. 记录Linux启动流程的工具bootchart

    /*********************************************************************  * Author  : Samson  * Date   ...

  10. java高新技术

    一.静态导入: import static语句导入一个类中的某个静态方法或所有方法: 例子: 1.import static java.lang.Math.max; 只是导入了Math类中的max方法 ...