5

Socket从 .NET 3.5 开始就有这些新的异步方法,用于与 SocketAsyncEventArgs 一起使用(例如Socket.SendAsync()),好处在于它们使用 IO 完成端口并避免需要继续分配。

我们制作了一个名为UdpStream的类,它有一个简单的接口——只有StartSend和一个Completed事件。它分配了两个 SocketAsyncEventArgs,一个用于发送,一个用于接收。StartSend 只是使用 SendAsync 发送消息,每秒调用大约 10 次。我们在接收 SocketAsyncEventArgs 上使用 Completed 事件,并且在每个事件处理后我们都 ReceiveAsync 以便它形成一个接收循环。同样,我们每秒接收大约 10 次。

我们的系统需要支持多达500个这样的UdpStream对象。换句话说,我们的服务器将与 500 个不同的 IP 端点同时通信。

我注意到在 MSDN SocketAsyncEventArgs 示例中,它们分配了 N x SocketAsyncEventArgs,一个用于您想要一次处理的每个未完成的接收操作。我不清楚这与我们的场景有什么关系——在我看来,也许我们没有从 SocketAsyncEventArgs 中受益,因为我们只是为每个端点分配一个。如果我们最终收到 500 个接收 SocketAsyncEventArgs,我想我们不会得到任何好处。也许我们仍然可以从 IO 完成端口中获得一些好处?

  • 当缩放到 500 时,此设计是否正确使用了 SocketAsyncEventArgs?

  • 对于我们使用单个“UdpStream”的情况,使用 SocketAsyncEventArgs 与使用旧的 Begin/End API 相比有什么好处吗?

4

2 回答 2

10

在我看来,也许我们没有得到 SocketAsyncEventArgs 的好处,因为我们只是为每个端点分配一个。如果我们最终收到 500 个接收 SocketAsyncEventArgs,我想我们不会得到任何好处。

仍然有很大的好处。

如果您使用 APM 模式(开始/结束方法),则每一个BeginSendBeginReceive分配一个IAsyncResult实例。这意味着每秒大约发生 10,000 次完整的类/对象分配(500*10 [发送] + 500*10 [接收])。这会给系统带来大量额外开销,因为它会增加大量 GC 压力。

切换到高性能网络应用程序的新建议方法,您将预先分配SocketAsyncEventArgs实例 (500) 并为每个方法调用重用它们,从而消除这些操作期间产生的 GC 压力。

于 2011-08-30T01:14:10.703 回答
6

Socket 从 .NET 3.5 开始就有这些新的异步方法,用于与 SocketAsyncEventArgs 一起使用(例如 Socket.SendAsync()),好处在于它们使用 IO 完成端口并避免需要继续分配。

Begin/End 方法也使用 IO Completion 端口。

对于我们使用单个“UdpStream”的情况,使用 SocketAsyncEventArgs 与使用旧的 Begin/End API 相比有什么好处吗?

恕我直言,你应该坚持你所知道的,因为你会让产品更快地启动和运行。但我也会创建一个严格的 IO 处理类来处理传输。如果运输性能被证明是瓶颈,则可以更轻松地切换到新模型。

于 2011-08-30T07:28:43.283 回答