Enterprise Services (.NET 1.1) Performance Guidelines - Resource Management

From Guidance Share
Jump to navigationJump to search

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



Optimize Idle Time Management for Server Applications

COM+ shuts down the host process (Dllhost.exe) after a configured period of inactivity (the idle time) from any client. By default, the process stays in memory for three minutes if there are no clients using the application. To optimize idle time management:

  • Consider increasing the idle time if clients tend to access components in short, sharp intervals in between lengthy periods of idle time. This will reduce the number of process restarts.
  • If your application contains a pool of objects, leave the process running idle to avoid having to repopulate the object pool. If you expect your component to be called every ten minutes, increase the idle time to a slightly longer time. For example, set it to twelve minutes.


To configure the idle time, use the Advanced page of the application's Properties dialog box in Component Services. Values in the range 1–1440 minutes are supported.


Always Call Dispose

Client code that calls serviced components must always call the object's Dispose method as soon as it is finished using it. Setting the object reference to null or Nothing is not adequate. If you do not call Dispose, unmanaged resources must go through finalization which is less efficient and more resource intensive. Clients that do not call Dispose can cause activity deadlock in multithreaded applications due to the asynchronous cleanup of object references. If you do not call Dispose on pooled objects that do not use JIT activation, the pooled objects are not returned to the pool until they go through finalization and garbage collection. By calling Dispose, you efficiently release the unmanaged resources (such as COM objects) used by the serviced component and reduce memory utilization.


Calling Dispose

For class methods, you can simply call Dispose as shown in the following sample.


  ComPlusLibrary comLib = new ComPlusLibrary();
  comLib.Dispose();


For interface methods, you need to cast to IDisposable as shown in the following sample:


  ServicedComp.ICom comLib = new ServicedComp.ComPlusLibrary();
  // comLib.Dispose();  // Dispose not available when using the interface
  ((IDisposable)comlib).Dispose(); // Cast to IDisposable


If your client code does not call Dispose, one workaround is to use the DisableAsyncFinalization registry setting, but with negative consequences as described later in this chapter.


References

For more information about calling Dispose and releasing serviced components, see the following " Knowledge Base articles:


DisableAsyncFinalization Registry Setting

If your managed client code does not call Dispose to release managed serviced components and you cannot change the client source code, as a last resort you can consider using the DisableAsyncFinalization registry key. This key prevents the serviced component infrastructure from co-opting user threads to help out with cleanup (leaving all the work to the finalizer thread).

To enable this feature, create the following registry key.


  HKLM\Software\Microsoft\COM3\System.EnterpriseServices
  DisableAsyncFinalization = DWORD(0x1)


If You Call COM Components, Consider Calling ReleaseComObject

Consider calling ReleaseComObject if you call COM components. Examples include hosting COM objects in COM+ and calling them from Enterprise Services or calling them directly from a managed client, such as ASP.NET. Marshal.ReleaseComObject helps release the COM object as soon as possible. Under load, garbage collection (and finalization) might not occur soon enough and performance might suffer.

ReleaseComObject decrements the reference count of the RCW, which itself maintains a reference count on the underlying COM object. When the RCW's internal reference count goes to zero, the underlying COM object is released.


Calling ReleaseComObject

Consider the following scenarios where you might need to call ReleaseComObject:

  • ASP.NET calling a COM component hosted in unmanaged COM+. The ASP.NET code should call ReleaseComObject when it has finished using the component.
  • ASP.NET calling a serviced component that wraps and internally calls a COM component. In this case, you should implement Dispose in your serviced component and your Dispose method should call ReleaseComObject. The ASP.NET code should call your serviced component's Dispose method.
  • Using a Queued Component recorder proxy or an LCE event class. In both cases, you are invoking unmanaged COM+ code.


Note If you call ReleaseComObject before all clients have finished using the COM object, an exception will be generated, if the object is subsequently accessed.


Marshal.Release

Calling the Marshal.Release method is unnecessary unless you manually manage object lifetime using Marshal.AddRef. It is also applicable when you call Marshal.GetComInterfaceForObject, Marshal.GetIUnknownForObject, or Marshal.GetIDispatchForObject to obtain an IUnknown interface pointer.


Summary of Dispose, ReleaseComObject, and Release Guidelines

You should only call ReleaseComObject where your managed code references an unmanaged COM+ component. In this instance, the unmanaged COM+ component will not provide a Dispose method. In cases where managed client code references a managed serviced component, the client code can and should call Dispose to force the release of unmanaged resources because all managed serviced components implement IDisposable. Table 8.4 summarizes when you need to call ReleaseComObject.

Client

Server

Call Dispose

Call ReleaseComObject

Call IUnknown Release

Managed

Managed component using ES

Yes

No

No

Managed

Unmanaged component using COM+

No

Yes

No

Unmanaged

Managed component using ES

Yes

No

Yes

Unmanaged

Unmanaged component using COM+

No

No

Yes

Table 8.4 When to Call Dispose, ReleaseComObject, and IUnknown.Release

Note that unmanaged code should always call IUnknown.Release. If unmanaged code references a managed component using Enterprise Services, it should also first call Dispose on the COM Callable Wrapper (CCW) through which it communicates with the managed object. If unmanaged code references an unmanaged COM+ component, it simply calls IUnknown.Release.

The following are general guidelines:

  • Cast to IDisposable. If the call is successful, call Dispose.
  • Cast to Marshal. If the call is successful, call ReleaseComObject.