用 .NET Memory Profiler 跟踪.net 应用内存使用情况--基本应用篇

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 / ( 1024 * 1024 )));
                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 = 0 ;
       
int _UnmanagedMemIncTimes = 0 ;

        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 [ 1024 * 1024 * _ManagedMemIncTimes]);
        }

       
/// <summary>
       
/// Increase unmanaged memory
       
/// </summary>
        public void IncUnmanagedMemory()
        {
            _UnmanagedMemIncTimes
++ ;

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


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




ContractedBlock.gif ExpandedBlockStart.gif MemoryLeakThread
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace TestMemorySize
{
   
class MemoryLeakThread
    {
        Thread _Thread;
       
byte[] _Buf;
       
int _Times = 0;

       
private void ThreadProc()
        {
           
while (true)
            {
                _Times
++;
                _Buf
= new byte[_Times * 1024 * 1024];
                Thread.Sleep(
30 * 1000);
            }
        }

       
public MemoryLeakThread()
        {
            _Thread
= new Thread(new ThreadStart(ThreadProc));
            _Thread.IsBackground
= true;
            _Thread.Start();
        }
    }
}


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


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


ManagedList.PNG


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


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


ManagedTypeDetail.PNG


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


ManagedInsDetail.PNG

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


ThreadList.PNG 


ThreadTypeDetail.PNG


ThreadInsDetail.PNG


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


SessionUnmanaged.PNG

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

UnmanagedList.PNG


 UnmanagedTypeDetail.PNG


UnmanagedInsDetail.PNG

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

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

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

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

转载于:https://www.cnblogs.com/gyweiUSTC/archive/2011/07/07/2100058.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值