gpt4 book ai didi

c# - 如何阻止异步 tcp .NET 代码用完整个系统的资源

转载 作者:可可西里 更新时间:2023-11-01 02:31:00 26 4
gpt4 key购买 nike

在我的一些异步tcp服务器代码中,偶尔会发生错误导致进程消耗整个系统的内存。在查看日志、事件查看器和一些MS docs如果“调用应用程序多次对同一个客户端进行异步 IO 调用,那么如果远程客户端停止其 I/O 结束,您可能会看到堆碎片和私有(private)字节增加”,就会出现问题,这会导致内存使用和固定出现峰值System.Threading.OverlappedData 结构和字节数组。

知识库文章提出的解决方案是“使用异步 IO 设置未完成(发送或接收)缓冲区数量的上限。”

如何做到这一点?这是指发送到 BeginRead 的 byte[] 吗?那么解决方案是简单地用信号量包装访问字节 [] 吗?

编辑:信号量控制对字节缓冲区的访问或仅具有静态大小的字节缓冲区池是两种常见的解决方案。我仍然担心的是,当这个异步客户端问题发生时(可能实际上是一些奇怪的网络事件),拥有信号量或字节缓冲池将阻止我用完内存,但它并没有解决问题。我的缓冲区池可能会被有问题的客户端吞噬,实际上将正确功能的合法客户端锁定在外。

编辑 2:遇到这个很棒的 answer .基本上它展示了如何手动取消固定对象。虽然异步 TCP 代码将固定留给幕后运行时规则,但可以通过在使用前显式固定每个缓冲区,然后在 block 末尾或 finally 中取消固定来覆盖它。我现在想弄清楚...

最佳答案

解决该问题的一种方法是预先分配异步通信中使用的缓冲区和其他数据结构。如果您在启动时预分配,就不会产生碎片,因为内存自然会驻留在堆的同一区域。

我建议使用添加到 .Net 3.5 SP1 的 ReceiveAsync/SendAsync API,它允许您缓存或预分配 SocketAsyncEventArgs结构和存储在 SocketAsyncEventArgs.Buffer 属性中的内存缓冲区,不像旧的 BeginXXX/EndXXX API 只允许缓存或预分配内存缓冲区。

使用旧的 API 也会产生大量的 CPU 成本,因为 API 会在内部一次又一次地创建 Windows Overlapped I/O 结构。在新的 API 中,这发生在 SocketAsyncEventArgs 中,因此通过合并这些对象,CPU 成本只需支付一次。

关于固定更新:固定是有原因的,即防止 GC 在碎片整理期间移动缓冲区。手动取消固定可能会导致内存损坏。

关于c# - 如何阻止异步 tcp .NET 代码用完整个系统的资源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10686346/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com