场景
使用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;