Object Pooling

The COM+ Object Pooling service enables you to reduce the overhead of creating each object from scratch. When an object is activated, it is pulled from the pool. When the object is deactivated, it is placed back into the pool to await the next request.

You can configure object pooling by applying the ObjectPoolingAttribute attribute to a class that derives from the System.EnterpriseServices.ServicedComponent class.

Object pooling lets you control the number of connections you use, as opposed to connection pooling, where you control the maximum number reached. Following are important differences between object pooling and connection pooling:

  • Creation. When using connection pooling, creation is on the same thread, so if there is nothing in the pool, a connection is created on your behalf. With object pooling, the pool might decide to create a new object. However, if you have already reached your maximum, it instead gives you the next available object. This is crucial behavior when it takes a long time to create an object, but you do not use it for very long.
  • Enforcement of minimums and maximums. This is not done in connection pooling. The maximum value in object pooling is very important when trying to scale your application. You might need to multiplex thousands of requests to just a few objects. (TPC/C benchmarks rely on this.)

COM+ object pooling is practically identical to .NET Framework managed SQL Client connection pooling. For example, creation is on a different thread and minimums and maximums are enforced.

**Note   **Application domains affect the behavior of object pooling. In Microsoft Windows 2000, when application activation is set to Library and you have multiple application domains, pooled objects are all created in the default application domain and shared between multiple clients. In the same situation, using Microsoft Windows XP and Windows Server 2003, there is one object pool per application domain. Using either operating system with multiple application domains and your application activation set to server, out-of-process clients use the object pool in the default application domain.

The following example sets size and time-out limits on the TestObjectPooling class:

<ObjectPooling(MinPoolSize := 2, MaxPoolSize := 5, _
CreationTimeout := 20000)> _
Public Class TestObjectPooling 
Inherits ServicedComponent
      Public Sub Perform ()
            ' Method contents go here.
      End Sub 
      Public Overrides Sub Activate()
            ' Called when removed from the pool.
      End Sub 
      Public Overrides Sub Deactivate()
            ' Called before deactivating or placing back in pool.
      End Sub 
      Public Overrides Function CanBePooled() As Boolean
            ' Called after Deactivate. Indicate your vote here.
            Return True
      End Function 
End Class 
[C#]
[ObjectPooling(Enabled=true, MinPoolSize=2, MaxPoolSize=5, CreationTimeOut=20000)]
public class TestObjectPooling : ServicedComponent
{
      public void Perform ()
      {
         // Method contents go here.
      }
      public override void Activate()
      {
         // Called when removed from the pool.
      }
      public override void Deactivate()
      {
         // Called before deactivating or placing back in pool.
      }
      public override bool CanBePooled()
      {
         // Called after Deactivate. Indicate your vote here.
         return true;
      }
}

Client

Public Class App
      Overloads Public Shared Sub Main(args() As String)
            Dim order As New TestObjectPooling()
            order.Perform()
            ' To return the object to the object pool, use DisposeObject.
            ' This returns the object to the pool and allows it to be reused.
            ' If this call is not made, the garbage collector returns it to the pool
            ' in a non-deterministic fashion, which hinders performance
            ' of an application that depends on object pooling to conserve 
            ' expensive resources. 
            ServicedComponent.DisposeObject (order)
      End Sub
End Class
[C#]
public class App
{
      public static int Main(string[] args)
      {
            TestObjectPooling order = new TestObjectPooling();
            order.Perform();
            /* To return the object to the object pool, use DisposeObject.
            This returns the object to the pool and allows it to be reused. 
            If this call is not made, the garbage collector returns it to the pool
            in a non-deterministic fashion, which hinders performance 
            of an application that depends on object pooling to conserve 
            expensive resources. */
            ServicedComponent.DisposeObject (order);
      }
}

**Note   **In general, you do not have to call DisposeObject from the client when using serviced components. However, it is necessary when you are using the COM+ Object Pooling service while the Just-in-Time (JIT) Activation service is not enabled. In this case, to verify that it is safe to return the object to the pool, COM+ needs to be notified when you are finished with the object. In general, if you intend to make only one call at a time on a pooled object, it is a good idea to enable JIT activation with object pooling. If you intend to get a reference and make multiple calls on it, using object pooling without JIT activation may result in better performance.

See Also

Summary of Available COM+ Services | ObjectPoolingAttribute | System.EnterpriseServices Namespace