Implementing Object Pooling with .NET Remoting
As you probably know, Object Pooling is a powerful feature available when hosting .NET or COM components in a COM+ application. I was quite surprised when I found out there was no built
The Pool Manager
The Pool Manager has been defined as a SAO singleton. This class exposes a CreateObject method which accepts an assembly name and a class name and returns an object instance peeked up from the pool.
To implement Singleton behavior correctly I’ve overridden the InitializeLifetimeService method to avoid having the singleton shut down by the lease manager after a period of inactivity.
In a default configuration, the time to leave of the object is 5 minutes; lifetime is extended by 2 minutes on each call. After that period the object will be no more accessible via remoting (but not necessarily destroyed since someone could reference it locally).
'this singleton never diesPublic Overrides Function InitializeLifetimeService() As Object Return NothingEnd Function
Keeping track of what objects are to be marked unavailable (since passed out to a client) is quite easy since we’ve explicitly control on this. But how does the object broker may ever know when an object can be returned to the pool?
Remoting Tracking Service comes to help.
If a class implements the ITrackingHandler interface, it can be registered to the remoting infrastructure in order to receive notification when any object in the Application domain is:
Marshaled: this event triggers on the server side when an object is passed out to a client
Unmarshaled: this event triggers on the client side when an object instance is acquired (note: it fires for CAO only)
Disconnected: this event triggers when an object is no more accessible through remoting. The disconnect event may fire due to lease timeout or due to explicit object removal (RemotingServices.Disconnect method)
Being able to determine when an object is passed out or disconnected from the remoting infrastructure, made the implementation of the Pool Manager very simple. All I had to do was to write some plumbing code to define and manage a proper in memory structure which keeps track of the state (available/unavailable) of each object in the different pools (there is, evidently, a pool for each object type).
The simple solution I end up is the following: The Pools Manager has an instance level hash table object. Each hashtable entry contains an instance of an ObjectPool class which holds information about a specific pool. The key of each hash table entry is defined via the string concatenation of the assembly and class name of the pooled class type.
The ObjectPool class extends the HashTable class in order to store references to objects in the pool and, additionally, pool’s general information such as its max and min size.
Each entry in this hash based class holds an object which simply wraps a specific object instance in the pool (ObjInstance class). This little wrapper is simply required to flag each object in the pool with an available/unavailable flag.
Got you confused ? I think so 🙂 . If you take a look at the picture below, you will certainly understand better the data structure used to hold object pools information.
When an activation requests arrives, the Object Broker first checks if a pool for the required object already exists. In case there is no such pool, the broker tries to get the required object type to see if it has a Pooling attribute attached. In case of a positive outcome, it creates the structure for a new object pool: creates a new Pool class, add it to the instance level hash table and then populate the pool with as many objects as specified in the Min property of the custom attribute.
Private Sub CreatePool(ByVal p_AssemblyName As String, ByVal p_ObjectName As String) Try 'Extract pool attributes