c#

位置:IT落伍者 >> c# >> 浏览文章

如何查找.NET程序内存不断上涨的原因[1]


发布日期:2019年02月22日
 
如何查找.NET程序内存不断上涨的原因[1]

我们知道NET是带有垃圾回收机制的出现这种情况一般是由某些数据长期存活在内存中又不能被当成垃圾数据回收的原因造成的

后来就在各搜索引擎上进行了各种搜索有说使用windebug分析dump但需要大量时间琢磨有人说是不是硬件问题还有人说中毒了最后找到了一款微软推出的CLRProfiler工具貌似很强大遂MSDN了一把MSDN是这样说的

Who allocates what on the managed heap

Which objects survive on the managed heap

Who is holding on to objects

What the garbage collector does over the lifetime of your application

得到这些信息以后就决定使用一下让服务端运行了一会儿停止以后得到分析结果最终在Allocation Graph视图下了解到原来是下载文件DownloadFile方法下的byte[]数组引起的短短不到一分钟的时间竟然占用了两百多兆的内存好了这下可找到原凶有得折腾了

方案:把要下载的数据一并加载到内存用户在下载的时候通过position来获取byte[]不新建直接返回是能解决问题但这就大大降低了服务端的可用性啊只能当做小文件服务端太不合理

方案:由于下载文件的时候返回的是一个可序列化的类所以想是不是这里出现了问题可以直接返回byte[]以最基本的数据头>数据长度>数据>数据尾来实现但这样一来要改的东西太多了服务端客户端协议重构眼看着就要落幕的项目却要重头再来心有不甘那再加上还有一堆任务在后面赶着这不是坑自己吗也放弃了

然后又回到各种网络资料搜索上经过一番查找后了解到byte[]最终也是会被回收的只要是托管的数据都是能被回收的只是周期可能会长一些最后又回到了Remoting本身上抱着试一试的心态把WellKnowObjectMode由SingleTon改为了SingleCall跑了一晚上最后稳定在了M上下总算松了口气

使用SingleTon本来是想节省内存消耗的可没想到得不偿失如此的大费周折遂总结出SingleTon并不适合并发量大的服务端程序SingleTon是单线程模式在调用每个方法的时候都会被加锁猜测造成数据一直不能被释放的原因是由这些锁造成的由于连接的数量太多导致连接一直处于排队状态造成了后面连接的客户端响应过慢连接超时在这里也给大家一个教训还是用SingleCall实在

上面说了这么多只是跟大家分享一下解决问题的经验还有叙述了一下问题的所在如果各位有不同的见解请一定要指出来毕竟NET内存分配垃圾回收本就比较复杂

然事与愿违却柳暗花明

这篇文章的重点是讲如何使用CLRProfiler来查找NET程序的内存分配情况的下面就开始吧

下载CLR Profiler:http://searchmicrosoftcom/enus/DownloadResultsaspx?q=clr%profiler

可根据自己NET的版本下载相应的CLRProfiler下面以NET版本为例CLRProfiler可以分析应用程序服务和ASPNET编写的程序以下以应用程序为例为大家演示如何简单使用CLRProfiler

下面是一个拆箱装箱的例子CLRProfilerTestDemo通过这个例子来观察进程托管堆的分配和研究垃圾回收机制的行为表现代码如下

using System;

using SystemCollectionsGeneric;

namespace CLRProfilerTestDemo

{

class Program

{

static void Main(string[] args)

{

for (int i = ; i < * ; i++)

{

Boxing box = new Boxing()

}

EnvironmentExit(EnvironmentExitCode)

}

}

class Boxing

{

private List<object> box = new List<object>()

private List<int> unbox = new List<int>()

public Boxing()

{

for (int i = ; i < ; i++)

{

boxAdd(i)

unboxAdd((int)box[i])

}

}

}

}

[] []

               

上一篇:如何查找.NET程序内存不断上涨的原因[2]

下一篇:用ODP.NET执行SQL读取数据库记录的方法