解决.net的堆碎片化带来的内存占用过大的问题

场景

使用WCF开发的服务端在多个客户端登录后,其服务器的内存占用不断增加。

 

 

分析

使用Windbg分析得到内存碎片化严重,其中包含了非常大的空闲空间,最大的一块竟然有150M,真正使用的空间其实很小。若无限地任其扩大,之后应该会由于在大内存中查找对象的效率低而造成程序运行缓慢。

大的碎片后的对象类型主要是:System.ServiceModel.Channels.OverlappedContext和System.Byte[],并且使用对象引用跟踪大碎片后的System.Byte[]对象,发现也是WCF的连接相关对象。猜想这些对象可能在内存中被pin住。

如果能限制新创建的对象在空闲内存中分配就好了,可惜.net并没有提供这样的方式。

 或者如果可以重写System.ServiceModel.Channels.OverlappedContext的创建,那么就可以在应用程序启动时预先申请一块内存,将对象全在这块内存中创建。

 

解决

在应用程序启动时限制最大工作集内存(当前限制为约1G。还可以根据实际的业务压力实时地调整这个值的大小)

System.Diagnostics.Process.GetCurrentProcess().MaxWorkingSet = (IntPtr)1000000000;

  

 

参考

Large Object Heap fragmentation causes OutOfmemoryException

利用进程工作集MaxWorkingSet,限制.NET程序的内存占用

posted @ 2013-12-18 15:54  beta2013  阅读(709)  评论(0编辑  收藏  举报