views:

226

answers:

2

Hi,

Reading through the SendAsync, BeginAsync method illustrations of Sockets, I realized that it was suggested to pool SocketAsyncEventArgs instances saying that it is a better than BeginXX, EndXX async approach since each call creates an IAsyncResult instance.

I thought it was not that a great practice to pool objects that can be instantiated easily (such as SocketAsyncEventArgs). Object allocation is pretty fast and GC is optimized to handle short living objects efficiently. I tried that out implementing a pooling mechanism to see how it performs, actually allocation is faster on simple objects that do nothing but encapsulate some data in ctor. (Well, it was like profiling a DBMS by sending billions of SELECT 1 statements, that's why I'm here.)

I'm not asking which is better, I believe profiling the actual application would yield the answer but just curious about the benefits of pooling simple short living objects. Better GC performance? Low memory fragmentation? Does it worth to consider it during design?

From MSDN

The main feature of these enhancements is the avoidance of the repeated allocation and synchronization of objects during high-volume asynchronous socket I/O. The Begin/End design pattern currently implemented by the System.Net.Sockets.Socket class requires a System.IAsyncResult object be allocated for each asynchronous socket operation.

In the new System.Net.Sockets.Socket class enhancements, asynchronous socket operations are described by reusable SocketAsyncEventArgs objects allocated and maintained by the application. High-performance socket applications know best the amount of overlapped socket operations that must be sustained. The application can create as many of the SocketAsyncEventArgs objects that it needs. For example, if a server application needs to have 15 socket accept operations outstanding at all times to support incoming client connection rates, it can allocate 15 reusable SocketAsyncEventArgs objects for that purpose.

Thanks.

+1  A: 

A cache without an expiration policy is a memory leak. There's nothing in your question that suggests you have considered a good policy. If you don't have one then don't use a cache. If you do then test it to see if you can measure actual improvements.

Hans Passant
+1  A: 

The IAsyncResult interface includes an AsyncWaitHandle property of type WaitHandle. A WaitHandle consumes operating system resources.

In fact, WaitHandle implements the IDisposable interface, so the class implementing IAsyncResult should itself implement IDisposable.

This is all to say that hundreds of IAsyncResult instances lying around is not a memory issue - it's a resources issue. The new socket calls get rid of the need for hundreds of IDisposable objects lying around.

John Saunders