CodeDOM and Memory Usage

Published 18 October 07 10:33 AM | psheill 

CodeDOM is used by several other library components including WinForms, ASP.NET, XSLT and Web Services.  It can be used to automatically generate code at design time, such as from a visual form, and it can be used to generate code at runtime, "on the fly", for performance.  It provides fast performance because the code is compiled into an assembly, loaded by the CLR and then JIT compiled into native code.  It's been used successfully in many contexts since it was first released in .NET 1.0.

 

One aspect of this that may catch some customers offguard is that assemblies are never unloaded by the CLR, aside from entire AppDomain unloads.  Therefore each assembly created by CodeDOM will remain in the address space even if it is no longer used.  For most applications, this doesn't present a problem - there is a bound to the number of assemblies the applications loads, and when they are no longer needed, the pages can be swapped out to disk by the Windows Virtual Memory (VM) subsystem, so they don't affect the rest of the application.  We have seen a few cases where the application uses CodeDOM repeatedly without bound, however, leading to out-of-memory and related exceptions.  When we examined these situations, we noticed that there was actually lots of free memory, but it was so fragmented that it couldn't be used.  We were puzzled until we examined how many assemblies were loaded into the process.  We found nearly 40000!  The fragmentation arose because each assembly under 64 KB in size is loaded into a segment of 64 KB.  So a 16 KB assembly would cause 48 KB of address space to be wasted.  Repeat thousands of time and it's not hard to exhaust the available address space of a 32-bit CPU. 

 

The best way to avoid this situation is to limit the number of times your application generates and loads a new assembly.  Cache the assembly in memory rather than regenerating it.  For example, if you use the XSLTransform type, cache the result of the Load method rather than calling it repeatedly for the same XSL document.  Assuming you have less than 40000 XSL documents in use, that will completely solve your problem, and reduce the number of costly compilations to boot.

 

Here are some details of our investigation.  The exception we were seeing actually happened when we didn't have enough contiguous memory to start up an external process. 

 

Exception type: System.Runtime.InteropServices.ExternalException

Message: Cannot execute a program. The command being executed was "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\csc.exe" /noconfig /fullpaths @"C:\WINDOWS\TEMP\rvnypb_j.cmdline".

InnerException: <none>

StackTrace (generated):<none>

StackTraceString: <none>

HResult: 8

 

Here's some memory information from Windbg.  The last line indicates large amounts of fragmentation, leaving only individual 64KB segments available.

-------------------- State SUMMARY --------------------------

    TotSize (      KB)   Pct(Tots)  Usage

   31b0d000 (  814132) : 25.88%   : MEM_COMMIT

   7c5b9000 ( 2037476) : 64.77%   : MEM_FREE

   11f2a000 (  294056) : 09.35%   : MEM_RESERVE

 

Largest free region: Base 00000000 - Size 00010000 (64 KB)

 

Comments

# Techy News Blog » Blog Archive » CodeDOM and Memory Usage said on October 18, 2007 2:14 PM:

PingBack from http://www.artofbam.com/wordpress/?p=10235

New Comments to this post are disabled

Search

This Blog

Syndication

Page view tracker