Enterprise Services (.NET 1.1) Performance Guidelines - Object Pooling

From Guidance Share

Jump to: navigation, search

- J.D. Meier, Srinath Vasireddy, Ashish Babbar, and Alex Mackman


Contents

Return Objects to the Pool Promptly

Unmanaged COM+ objects return to the pool when their reference counts return to zero. Managed objects return to the pool only when garbage collected. There are several ways you can ensure an object is immediately returned to the pool and these vary depending on whether the object is configured for JIT activation:

  • With JIT activation, use ASAP deactivation.
  • Without JIT activation, the caller controls lifetime.


With JIT Activation, Use ASAP Deactivation

The context-maintained Done flag is initialized to false each time COM+ creates a new object in a context. If the Done flag is set to true when a method returns, COM+ deactivates and either destroys the object, or if object pooling is enabled, returns the object to the pool.

You can set the Done flag to true and force an object back to the pool in the following three ways:

  • Use the AutoComplete attribute. Upon completion of a method marked with this attribute, the COM+ runtime either calls SetComplete or SetAbort, depending on whether the method generates an exception. Both methods set the Done flag in the object's context to true, which ensures that the object is returned to the pool. Use of the AutoComplete attribute is shown in the following code sample.


  [ObjectPooling(MinPoolSize=0, MaxPoolSize=1)]
  [JustInTimeActivation()]
  public class YourClass : ServicedComponent
  {
     [AutoComplete]
     public void SomeMethod()
     {
        ...
     }
     ...
  }

Note Using this attribute is equivalent to selecting the Automatically deactivate this object when this method returns check box on a method's Properties dialog box in Component Services.


  • Set ContextUtil.DeactivateOnReturn=true at the end of your method as shown in the following code sample.


  public void SomeMethod()
  {
    // Do some work
    . . .
    // Make sure the object returns to the pool by setting DeacivateOnReturn
    ContextUtil.DeactivateOnReturn = true;
  }
  • Call ContextUtil.SetComplete or ContextUtil.SetAbort at the end of your method. Both methods set the Done flag to true. Transactional components also use these methods to vote for the outcome of a transaction. SetComplete represents a vote for the transaction to commit while SetAbort votes for a transaction rollback.

Note Transaction outcome is dependent on the voting of all objects participating in the current transaction.

  public void SomeMethod()
  {
    // Do some work
    . . .
    // Calling SetComplete (or SetAbort) sets the Done flag to true
    // which ensures the object is returned to the pool.
    ContextUtil.SetComplete();
  }


Without JIT Activation, the Caller Controls Lifetime

If your pooled object is not configured for JIT activation, the object's caller must call Dispose and therefore controls the lifetime of the object. This is the only way Enterprise Services can know when it is safe to return the object to the pool.

Note Clients should always call Dispose on a disposable object regardless of the JIT activation setting. For more information, see "Resource Management" later in this chapter.

In C#, you can use the using keyword to ensure that Dispose is called.


  // your pooled object's client code
  public void ClientMethodCallingPooledObject()
  {  
     using (YourPooledType pooledObject = new YourPooledType())
     {
          pooledObject.SomeMethod();
     } // Dispose is automatically called here
  }


Monitor and Tune Pool Size

COM+ automatically adjusts the pool size to meet changing client loads. This behavior is automatic, but you can fine tune the behavior to optimize performance for your particular application. If the pool size is too large, you incur the overhead of populating the pool with an initialized set of objects, many of which remain redundant. Depending on the nature of the object, these objects might unnecessarily consume resources. Also, unless you manually start the application before the first client request is received, the first client takes the associated performance hit as the pool is populated with objects.


Preload Applications That Have Large Minimum Pool Sizes

When an application is started, it initializes the object pool and creates enough objects to satisfy the configured minimum pool size. By manually starting an application before the first client request is received, you eliminate the initial performance hit that the initial request would otherwise entail.

To automate application startup, you can use the following script code.


  Dim oApplications 'As COMAdminCatalogCollection
  Dim oCatalog 'As COMAdminCatalog
  Dim oApp 'As COMAdminCatalogObject
  Set oCatalog = CreateObject("ComAdmin.COMAdminCatalog")
  Set oApplications = oCatalog.GetCollection("Applications")
  oApplications.Populate
  For Each oApp In oApplications
    If oApp.Name = "<Provide Your Server Application Name>" Then
      Call oCatalog.StartApplication(oApp.Name)
      Wscript.Echo oApp.Name + "Started..."
    End If
  Next

Note The automation script code applies only for server applications and not for library applications.


References

For more information about object pooling, see Microsoft Knowledge Base article 317336, "HOW TO: Use Enterprise Services Object Pooling in Visual Basic .NET," at http://support.microsoft.com/default.aspx?scid=kb;en-us;317336.

Personal tools