Reading through the SendAsync
, BeginAsync
method illustrations of Socket
s, 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开发者_如何学C socket accept operations outstanding at all times to support incoming client connection rates, it can allocate 15 reusable SocketAsyncEventArgs objects for that purpose.
Thanks.
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.
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.
精彩评论