Microsoft KB Archive/297997

= PRB: MSXML Performance Bottleneck in ShareMutex Under Stress =

Article ID: 297997

Article Last Modified on 6/4/2003

-

APPLIES TO


 * Microsoft Data Access Components 2.5
 * Microsoft Data Access Components 2.5 Service Pack 1
 * Microsoft Data Access Components 2.5 Service Pack 2
 * Microsoft Data Access Components 2.6
 * Microsoft Data Access Components 2.6 Service Pack 1
 * Microsoft Data Access Components 2.6 Service Pack 2
 * Microsoft Data Access Components 2.7
 * Microsoft XML Parser 2.5
 * Microsoft XML Parser 2.6
 * Microsoft XML Core Services 4.0
 * Microsoft XML Parser 3.0 Service Pack 1
 * Microsoft XML Parser 3.0 Service Pack 2
 * Microsoft XML Core Services 4.0
 * Microsoft XML Core Services 4.0 Service Pack 1

-



This article was previously published under Q297997



IMPORTANT: This article contains information about modifying the registry. Before you modify the registry, make sure to back it up and make sure that you understand how to restore the registry if a problem occurs. For information about how to back up, restore, and edit the registry, click the following article number to view the article in the Microsoft Knowledge Base:

256986 Description of the Microsoft Windows Registry



SYMPTOMS
When you use the MSXML parser in a high-stress environment such as Microsoft Internet Information Services (IIS), a bottleneck may occur while the MSXML parser performs garbage collection, such as around the msxml3!ShareMutex__SleepWaitingForLock internal MSXML function. This may cause unusually long run times on XML requests, and the application or service can appear to stop responding (hang). However, if the stress is removed from the application or service, the requests are eventually run and the process stabilizes.

For additional information about the garbage collection mechanism with the MSXML parser, click the article number below to view the article in the Microsoft Knowledge Base:

304227 Understanding the MSXML Garbage Collection Mechanism



CAUSE
This behavior is a result of contention on locks in the DOMDocument object class factory. The locks must be acquired whenever a DOMDocument object is created or destroyed. Each time the internal reference count of active objects for MSXML drops to zero and a DOMDocument object is unloaded, extensive locking and processor activity occurs. Because Active Server Pages (ASP) pages run in single threaded apartments (STAs), each Web page that uses a local DOMDocument object instantiates its own copy, meaning that every page that is using the local DOMDocument object incurs the overhead of object creation and deletion.

When numerous threads simultaneously create and destroy Document Object Model (DOM) objects, the locks in the class factory may experience significant contention. The threads enter a wait state, with each thread waiting for its turn at the locks. Although this is not a true deadlock, a thread that executes a client request can take an unexpectedly long time to complete.



RESOLUTION
WARNING: If you use Registry Editor incorrectly, you may cause serious problems that may require you to reinstall your operating system. Microsoft cannot guarantee that you can solve problems that result from using Registry Editor incorrectly. Use Registry Editor at your own risk.

To resolve this problem, upgrade to the latest version of the MSXML parser.

With MSXML 3.0 Service Pack 2 (SP2) and later, changes to the implementation of DOMDocument are included with other performance improvements. This upgrade may reduce the bottleneck that is caused by this issue.

NOTE: MSXML 3.0 SP2 only installs in Replace mode. For additional information, click the article number below to view the article in the Microsoft Knowledge Base:

321924 INFO: MSXML 3.0 Service Pack 2 Installs Only in Replace Mode

With MSXML 4.0 Service Pack 1 (SP1) and later, there is a new feature is implemented in the parser to turn off FullGC automatically if a certain number of threads are waiting for garbage collection.

NOTE: MSXML 4.0 only installs and runs in side-by-side mode. MSXML 4.0 is more compliant with World Wide Web Consortium (W3C) XML specifications. An application that relies on behavior that does not comply with the W3C specifications may need additional compatibility tests.

In addition to upgrading to the latest version of MSXML parser, there are two recommended workarounds for this problem, and each workaround is appropriate depending upon the situation in which it is used. These workarounds are generalized, and may not work perfectly in every situation. Unforeseen results may occur, and you must consider each situation carefully before you implement either of these workarounds.

For each workaround, you must use the FreeThreadedDOMDocument object instead of the DOMDocument object, because the DOM must be loaded into a multi-threaded apartment (MTA) to keep it from unloading after each ASP page is complete. The DOMDocument is not supported in an MTA, but the FreeThreadedDOMDocument is.

Using Component Services or MTS to Load the DOM Out of Process
This technique loads the XML DOM object in its own out-of-process server package and places it in an MTA for the hosting process. This approach affects the creation of all DOM objects system-wide.

Consider this technique in cases in which the following are true:
 * The application has already been written, so that changes to avoid the object creation require a complete rewrite.
 * The Web server sustains a moderate to high number (15 or more) of ASP pages that each use XML simultaneously.
 * XML is integrated into an existing Web application that precludes the use of a global XML object.

Do not use this workaround if less than 15 threads access the DOM at the same time. The overhead of marshalling calls to the out-of-process DOM actually results in performance degradation with less than 15 threads.

To use Component Services or MTS to load the DOM out of process, follow these steps:  Create a Component Services or MTS package and import the MSXML FreeThreadedDOMDocument into the new package. Change the threading model for the FreeThreadedDOMDocument in the registry to Free. This registry key is found in the following location:

HKEY_CLASSES_ROOT\CLSID\\InProcServer32\ThreadingModel

The default value for this key is Both. This is required for the object to run in the Component Services or MTS package. Make sure that the package is marked for server activation (out-of-process) instead of library activation (in-process). This is the default setting on Microsoft Windows 2000, but must be manually configured on Microsoft Windows NT 4.0.

Using an Application Scope DOM to Prevent Unnecessary Garbage Collection
Consider this technique in cases in which forcing all XML DOM objects to load in the MTA of a separate process is not a valid option. This may apply in situations in which you have Web servers that have numerous Web sites and you want to control the lifetime of the XML DOM on a case-by-case basis, or in which only a few long-lived XML documents are created.

This workaround is not system-wide and must be applied independently to each Web site that experiences the problem.

Although this workaround does not incur the marshalling overhead of the first workaround, it has the disadvantage that if the DOM crashes for any reason, the Web site stops responding (hangs). If the DOM crashes in the first workaround, its host process dies and Component Services or MTS instantiates a new host process when the next request comes through. Also, using a global DOM causes all calls to be serialized, which may affect performance.

To use an application-scope DOM to prevent unnecessary garbage collection, follow these steps:  Create a global instance of the FreeThreadedDOMDocument in Application_OnStart for the Web site that has the problem. This global &quot;dummy&quot; object prevents the reference count on the DOM from reaching zero, so that the DOM does not unload until the application shuts down.</li> Change the threading model for the FreeThreadedDOMDocument in the registry to Free. This registry key is found in the following location:

HKEY_CLASSES_ROOT\CLSID\Class ID of the version of the FreeThreadedDOMDocument being used\InProcServer32\ThreadingModel

The default value for this key is Both. This is required for the object to run in application scope.</li></ol>

NOTE: The Class IDs to be substituted in these registry keys are as follows, depending on the version of MSXML that is being used:
 * 3.0 - {F6D90F12-9C73-11D3-B32E-00C04F990BB4}
 * 2.6 - {F5078F1C-C551-11D3-89B9-0000F81FE221}

NOTE: For this workaround, the main purpose of creating a global FreeThreadedDOMDocument at application scope is to prevent the global count of objects tracked by MSXML parser from ever reaching zero (that is, to prevent the expensive full garbage collection from occurring). ASP pages can still use the regular DOMDocument object without modification.

<div class="moreinformation_section">

MORE INFORMATION
If a debugger is attached to the process and the threads are examined, a number of threads have call stacks that look like one or both of the following sample call stacks: <pre class="fixed_text"> 81  id: f0f0f0f0.698   Suspend: 1 Teb 7ff68000 Unfrozen ChildEBP RetAddr Args to Child 057df0f0 77e86a15 00000a38 00000000 00000000 ntdll!ZwWaitForSingleObject+0xb (FPO: [3,0,0]) 057df118 77e86a3d 00000a38 ffffffff 00000000 KERNEL32!WaitForSingleObjectEx+0x71 (FPO: [Non-Fpo]) 057df128 69b22471 00000a38 ffffffff 77e8666a KERNEL32!WaitForSingleObject+0xf (FPO: [2,0,0]) 057df13c 69b1a67f ffffffff 02dbb2ec 02dbb2d8 msxml3!ShareMutex__SleepWaitingForLock+0x21 (FPO: [1,0,2]) 057df154 69b11377 ffffffff 00000000 052446d0 msxml3!ShareMutex__WaitForExclusiveLock+0x79 (FPO: [EBP 0x057df200] [1,0,4]) 057df168 69b13cef ffffffff 00000000 052446d0 msxml3!ShareMutex__ClaimExclusiveLock+0x27 (FPO: [1,0,3]) 057df180 69b13e28 052446d0 052446d0 69b13dd2 msxml3!AddPointerToCache+0x22 (FPO: [EBP 0x00000000] [1,0,4])

88 id: f0f0f0f0.51c   Suspend: 1 Teb 7ff70000 Unfrozen ChildEBP RetAddr Args to Child 06a6f0ac 77e86a15 00000a3c 00000000 00000000 ntdll!ZwWaitForSingleObject+0xb (FPO: [3,0,0]) 06a6f0d4 77e86a3d 00000a3c ffffffff 00000000 KERNEL32!WaitForSingleObjectEx+0x71 (FPO: [Non-Fpo]) 06a6f0e4 69b22471 00000a3c ffffffff 77e8666a KERNEL32!WaitForSingleObject+0xf (FPO: [2,0,0]) 06a6f0f8 69b1a67f ffffffff 02dbb324 02dbb310 msxml3!ShareMutex__SleepWaitingForLock+0x21 (FPO: [1,0,2]) 06a6f110 69b11377 ffffffff 0610fbb0 06a6f148 msxml3!ShareMutex__WaitForExclusiveLock+0x79 (FPO: [EBP 0x06a6f14c] [1,0,4]) 06a6f124 69b11784 ffffffff 69b114e2 0610fbb0 msxml3!ShareMutex__ClaimExclusiveLock+0x27 (FPO: [1,0,3]) 06a6f12c 69b114e2 0610fbb0 69b47a21 02dbb310 msxml3!ShareMutex__Enter+0x7 (FPO: [0,0,0]) 06a6f134 69b47a21 02dbb310 03478284 00000000 msxml3!MutexLock__MutexLock+0x1a (FPO: [1,0,1]) 06a6f14c 69b121d0 00000000 03478280 0347823c msxml3!Base__testForGC+0x7c (FPO: [Non-Fpo])

<div class="references_section">