kma*_*ks2 8 .net c# asynchronous tcp
在我的一些异步tcp服务器代码中,偶尔会发生错误,导致进程占用整个系统的内存.在查看日志,事件查看器和一些MS文档时,如果"调用应用程序多次向同一客户端调用异步IO,那么如果远程客户端停止其结束,则可能会看到堆碎片和私有字节增加"/O"导致内存使用量激增以及System.Threading.OverlappedData结构和字节数组的固定.
知识库文章提出的解决方案是"设置未完成缓冲区(发送或接收)与异步IO的上限."
怎么做到这一点?这是指发送到BeginRead的byte []吗?那么解决方案只是用信号量包装访问byte []?
编辑:信号量控制访问字节缓冲区或只是具有静态大小的字节缓冲池是两种常见的解决方案.我仍然存在的一个问题是,当这个异步客户端问题发生时(实际上它可能是一些奇怪的网络事件)有信号量或字节缓冲池将阻止我耗尽内存,但它无法解决问题.我的缓冲池可能会被问题客户端吞噬,实际上锁定了正确的函数合法客户端.
编辑2:遇到了这个伟大的答案.基本上它显示了如何手动取消固定对象.虽然异步TCP代码可以固定到幕后运行时规则,但有可能通过在使用前明确地固定每个缓冲区来覆盖它,然后在块的末尾或最后一个中取消固定.我现在想弄明白......
解决该问题的一种方法是预先分配异步通信中使用的缓冲区和其他数据结构。如果在启动时进行预分配,则不会产生碎片,因为内存自然会驻留在堆的同一区域中。
我建议使用.Net 3.5 SP1 中添加的ReceiveAsync/ SendAsyncAPI,它允许您缓存或预分配属性SocketAsyncEventArgs中存储的结构和内存缓冲区SocketAsyncEventArgs.Buffer,这与旧的BeginXXX/ EndXXXAPI 不同,后者仅允许缓存或预分配内存缓冲区。
使用旧的 API 也会产生大量的 CPU 成本,因为 API 内部一次又一次地创建 Windows 重叠 I/O 结构。在新的 API 中,这发生在 中SocketAsyncEventArgs,因此通过池化这些对象,CPU 成本只需支付一次。
关于固定的更新:固定是有原因的,即防止 GC 在碎片整理期间移动缓冲区。通过手动取消固定,可能会导致内存损坏。
| 归档时间: |
|
| 查看次数: |
1309 次 |
| 最近记录: |