6月30日,我们发布异步改造后的博客程序后,出现了高内存、高CPU、高线程数的不尽如人意的情况。经过一周的排查,终于水落石出——造成不尽如人意情况的根本原因是我们修改后的EnyimMemcached代码中的内存泄漏问题。内存泄漏的根本原因是我们没有处理SocketAsyncEventArgs。实际情况是我们根本没有注意到SocketAsyncEventArgs实现了IDispose接口,这个小疏忽居然折腾了我们一个星期。有内存泄漏问题的代码是这样写的:a)从Socket异步读取数据:publicasyncTaskReadBytesAsync(intcount){varargs=newSocketAsyncEventArgs();args.SetBuffer(newbyte[count],0,count);varawaitable=newSocketAwaitable(args);awaitthis.socket.ReceiveAsync(等待);返回参数。缓冲区;}b)将数据异步写入Socket:publicasyncTaskWriteSync(IList>buffers){varargs=newSocketAsyncEventArgs();args.BufferList=缓冲区;varawaitable=newSocketAwaitable(args);awaitthis.socket.SendAsync(等待);}解决内存泄漏问题的方法很简单,使用+Buffer.BlockCopy,代码如下:a)改进后的异步slavesocket读取数据:publicasyncTaskReadBytesAsync(intcount){using(varargs=newSocketAsyncEventArgs()){args.SetBuffer(newbyte[count],0,count);varawaitable=newSocketAwaitable(args);awaitthis.socket。接收异步(等待);varreceivedBytes=newByte[args.BytesTransferred];Buffer.BlockCopy(args.Buffer,0,receivedBytes,0,args.BytesTransferred);返回接收字节;}}b)改进了向Socket异步写入数据:publicasyncTaskWriteSync(IList>buffers){使用(varargs=newSocketAsyncEventArgs()){args.BufferList=buffers;varawaitable=newSocketAwaitable(args);awaitthis.socket.SendAsync(等待);}}改进后的代码已经发布到github:https://github.com/cnblogs/EnyimMemcached你可能会问我们如何检测内存泄漏?我们求助于两个工具:Windows任务管理器和性能监视器。1、通过任务管理器,我们观察到w3wp占用的内存会不断增长。到了5G左右,8核8G阿里云虚拟机上的CPU就开始坐过山车了。只有回收程序池(重启w3wp进程)才能恢复正常。2.通过PerformanceMonitor,我们监测了两个指标:a)\.NETCLRMemory(w3wp)\#BytesinallHeaps(formanagedmemory)b)\Process(w3wp)\PrivateBytes(forunmanagedmemory)观察到的情况如下图所示:(绿色为PrivateBytes)所有Heaps中的Bytes和PrivateBytes都将继续增长。处理完SocketAsyncEventArgs后,performancemonitor看到的\.NETCLRMemory\#BytesinallHeaps变成了这样:\Process\PrivateBytes也补充了BytesinallHeaps:看到这样的图,你应该觉得辛苦了后面的GC跟我们做的一样。原文链接:http://www.cnblogs.com/cmt/p/sokcet_memory_leak.html