Paul Wilson emailed me with some questions regarding perceived memory leaks related to System.Xml.Serialization.XmlSerializer. I questioned whether it would be a “memory leak”, but pinged Christoph Schittko for some backup evidence. He said he doubted it as well, else web services everywhere would be falling on their faces. I pointed him to Doug Purdy's post on inspecting theXmlSerializer's interim assembly, and Chris Sells' utility for precompiling XmlSerializer types.
Paul emailed back that, in fact, they pinpointed the leak, and it was related to the XmlSerializer. But it is not a memory leak... it is a dynamically created assembly “leak“, and is not by accident, but rather by design.
XmlSerializer manages the generation and execution of per-type reader/writer pairs. These pairs are dynamically generated types that extend the internal types XmlSerializationReader and XmlSerializationWriter, respectively. When instantiating an XmlSerializer, you must provide a System.Type object that represents the type the new serializer object will be used with. To avoid generating redundant assemblies, the XmlSerializer constructor looks in an AppDomain-wide cache of generated reader/writer assemblies and reuses the cached assembly if one is found. If one is not found, the XmlSerializer constructor generates a new dynamic assembly by reflecting against the presented System.Type object. This new assembly is added to the cache so subsequent XmlSerializer objects can reuse it, reducing overall code size and codegen overhead. Unfortunately, the cache only works for some constructors of XMLSerializer, since the lookup index gets more complex with more overrides. Users can cache the serializer themselves—it's freethreaded so you can serialize across threads.
[Don Box, MSDN Magazine, House of Web Services, November 2001]
Christoph followed up with (via IM):
I got used to the pattern of having a static serializer instance in my apps ... Just instantiate it once, assign it to a private or internal static property somewhere in the assembly. Then you don't even need to hit the cache ...
It's also interesting to note, that System.Messaging does not rely on the cache and keeps its own cache around.
For those that haven't read it, you really need to read Christoph's blog entry on troubleshooting the XmlSerializer.