.NET异步套接字:让SocketAsyncEventArgs的任何好处在这种情况下在开始/结束?在这种情况下、好处、结束、NET

2023-09-05 22:59:20 作者:安稳随性

插座有这些因为.NET 3.5 与的SocketAsyncEventArgs使用新的异步方法(如Socket.SendAsync()),他们使用的IO完成端口,避免需要保持分配收益的引擎盖下是。

我们已经取得了一个类的的 UdpStream 的有一个简单的界面 - 只的 StartSend 的和的已完成的事件。它分配2的SocketAsyncEventArgs,一个用于发射和一个用于接收。该StartSend简单地调度使用SendAsync的消息,被称为10次。我们使用在接收的SocketAsyncEventArgs Completed事件,和之后每个事件处理大家都ReceiveAsync使得它形成了一个接收环。同样,我们每秒钟收到的大约10倍。

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

我注意到在MSDN的SocketAsyncEventArgs的例子,他们分配的N×的SocketAsyncEventArgs,每一个优秀的接收要处理一次操作。我不清楚究竟如何这涉及到我们的场景 - 在我看来,也许我们没有得到的SocketAsyncEventArgs的优势,因为我们只是分配每个端点一个。如果我们最终有500接收的SocketAsyncEventArgs我presuming我们会得到任何好处。也许我们仍然得到一些受益于IO完成端口?

这是否设计,使正确使用的SocketAsyncEventArgs时 扩展到500?

对于我们在那里有一个单一的UdpStream中使用的情况下,有 任何好处在于使用的SocketAsyncEventArgs VS使用较早的开始/结束的API?

解决方案   

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

还有一个巨大的好处。

.NET多线程和异步总结 一

如果您使用APM模式(开始/结束的方法),每个 BeginSend 和每 BeginReceive 分配一个 IAsyncResult的的实例。这意味着有发生每秒约10000次完整的类/对象分配(500 * 10 [发送] + 500 * 10 [接收])。这使得大量的额外开销,在系统中,因为它会增添了不少的GC pressure。

切换到高性能的网络应用的新建议的方法,你会preallocate的的SocketAsyncEventArgs 实例(500)和重用它们对于每一个方法调用,从而避免了在这些操作中创建的GC pressure。

Socket has these new async methods since .NET 3.5 for use with SocketAsyncEventArgs (e.g. Socket.SendAsync()), benefits being under the hood they use IO completion ports and avoid the need to keep allocating.

We have made a class called UdpStream with a simple interface - just StartSend and a Completed event. It allocates two SocketAsyncEventArgs, one for send and one for receiving. The StartSend simply dispatches a message using SendAsync, and is called about 10 times a second. We use the Completed event on the receive SocketAsyncEventArgs, and after each event is handled we all ReceiveAsync so that it forms a receive loop. Again, we receive roughly 10 times per second.

Our system needs to support up to 500 of these UdpStream objects. In other words our server will communicate concurrently with 500 different IP endpoints.

I notice in the MSDN SocketAsyncEventArgs examples that they allocate N x SocketAsyncEventArgs, one for each outstanding receive operation you want to handle at one time. I am not clear exactly how this relates to our scenario - it seems to me that perhaps we are not getting the benefit of SocketAsyncEventArgs because we are simply allocating one per endpoint. If we end up with 500 receive SocketAsyncEventArgs I am presuming we will get no benefit. Perhaps we still get some benefit from IO completion ports?

Does this design make correct use of SocketAsyncEventArgs when scaling to 500?

For the case where we have a single "UdpStream" in use, is there any benefit to using SocketAsyncEventArgs vs using the older Begin/End API?

解决方案

it seems to me that perhaps we are not getting the benefit of SocketAsyncEventArgs because we are simply allocating one per endpoint. If we end up with 500 receive SocketAsyncEventArgs I am presuming we will get no benefit.

There is still a huge benefit.

If you use the APM pattern (Begin/End methods), each and every BeginSend and every BeginReceive allocate an IAsyncResult instance. This means there's a full class/object allocation occurring roughly 10,000 times per second (500*10 [send] + 500*10 [receive]). This puts a huge amount of extra overhead in the system since it's going to add a lot of GC pressure.

Switching to the new suggested method for high performance networking applications, you'd preallocate the SocketAsyncEventArgs instances (500) and reuse them for every method call, thereby eliminating the GC pressure created during these operations.