Automatic DLL unloading in BizTalk interferes with data caching
In BizTalk we often cache data in memory to improve performance, for example conversion tables or configuration data. Cached data is usually kept in static variables. When a DLL is released from memory, all of his static members are released as well. When we write our application, DLLs are not unloaded until the application is shutdown, unless we specify this explicitly.
BizTalk implements an internal logic of unloading DLLs from its memory. By default it unloads DLLs that have not been active for 30 minutes. If there is no instance of any of the orchestration types in a DLL, it will be unloaded already after 20 minutes. This mechanism also releases the regular NET DLLs that are referenced by the BizTalk DLLs.
The rational is that we do not want to keep in memory DLLs we do not need, as it would be a waste of memory resources. The problem is that it means that when we create caches BizTalk default setup unloads them if they have not been used for over half an hour.
We encountered a few cases of clients that complained about slow response from a service on the first call in the morning. This is because the first call included the loading time of the cache that was released during the night, when there was no activity. Another case was with a service that was called only a few times a day. We needed to improve its latency, and tried to do so by caching some conversion data in order to save roundtrips to the DB. We found that we increased the response time, as it turned out that each service call was loading an entire table and building the cache hashtable.
BizTalk enables us to control this mechanism. In the documentation there is a “hidden” page that describes various
sections you can add to the BizTalk config file, one of which tells BizTalk how the unload logic should be for specific DLLs.
In this section you define AppDomains and which DLLs belong to them. Then you instruct each AppDomain how many seconds to wait before it should unload DLLs. If you specify "-1", the DLLs will never be unloaded. It is possible to specify which DLLs belong to an AppDomain by explicitly using a DLL full name, or through regular expression filters to match DLLs name patterns.
When writing a cache we plan to control when the data is loaded, and more importantly when it is released. If we are not aware of the automatic unloading mechanism of BizTalk, our caches will not behave as we planned. We need to add a configuration section and specify that the DLLs that do the caching will not be unloaded.
Here is an example of what it should look like:
<?xml version="1.0" ?>
<configuration>
<configSections>
<section name="xlangs"
type="Microsoft.XLANGs.BizTalk.CrossProcess.
XmlSerializationConfigurationSectionHandler,
Microsoft.XLANGs.BizTalk.CrossProcess" />
</configSections>
<xlangs>
<Configuration>
<AppDomains AssembliesPerDomain="10">
<DefaultSpec SecondsIdleBeforeShutdown="1200"
SecondsEmptyBeforeShutdown="1800"/>
<AppDomainSpecs>
<AppDomainSpec Name="MyCachingDomain"
SecondsIdleBeforeShutdown="-1"
SecondsEmptyBeforeShutdown="-1"/>
</AppDomainSpecs>
<ExactAssignmentRules>
<ExactAssignmentRule AssemblyName="MyCache1, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=9c7731c5584592ad"
AppDomainName="MyCachingDomain="/>
</ExactAssignmentRules>
<PatternAssignmentRules>
<PatternAssignmentRule AssemblyNamePattern="MyCache*"
AppDomainName="MyCachingDomain" />
</PatternAssignmentRules>
</AppDomains>
</Configuration>
</xlangs>
</configuration>
You can download the sample above from here BizTalk DLL Unloading.zip. The zip contains also a more detailed example with all the config options including explanations about each field can be downloaded here This is a corrected version I made of the sample in the BizTalk documentation which is erroneous. The source there includes garbage text that makes the config XML invalid. Also, in my version I simplified the explanations and removed parts that are not related to the unload logic. The parts that have been removed are additional configurations of the AppDomain which can also be very useful but are out of scope for this post.