XmlSerializer Performance Issue
Ever notice that making a call to new a System.Xml.Serialization.XmlSerializer is really slow?
As it turns out, the XmlSerializer constructor is slow since it creates the serialization and deserialization code and compiles it into a temporary assembly at runtime. This occurs for each type that is passed in as a parameter to the XmlSerializer constructor.
On older machines or machines where the performance is I/O bound, the time it takes for the constructor call balloons very quickly. I’ve seen it take as long as 8 seconds.
The fact is that in the majority of cases, you will not need to have this functionality at runtime since the binding of the object graph and the XML will be known at compile time.
Workaround in the .Net Framework 1.0 and 1.1
In .Net 1.0 and 1.1, you could workaround this issue by capturing the generated code in a test run, write an XmlSerializer subclass and use that instead.
In order to capture the XmlSerializer generated code, you need to set a diagnostic switch in the application config file of the app:
<gcConcurrent enabled="true" />
<publisherPolicy apply="yes" />
<probing privatePath="bin\debug" />
<add name="XmlSerialization.Compilation" value="4"/>
After performing a test run with this app config file, the generated code can be found in the temp folder. Now that you have that code, you need to write a subclass of the XmlSerializer that looks something like this (the actual names of the methods and classes are generated and are subject to change):
public class MySerializer : XmlSerializer
protected override XmlSerializationReader CreateReader()
return new XmlSerializationReader1();
protected override XmlSerializationWriter CreateWriter()
return new XmlSerializationWriter1 ();
public override Boolean CanDeserialize(XmlReader xmlReader)
protected override void Serialize(Object objectToSerialize, XmlSerializationWriter writer)
protected override System.Object Deserialize(XmlSerializationReader reader)
Given that you’ve added the class above and the generated code to your project, the last thing that remains is to change your instantiation of the XmlSerializer:
XmlSerializer serializer = new XmlSerializer(typeof(Options));
XmlSerializer serializer = new MySerializer();
The MySerializer() constructor is empty so it takes 0 time. All the time spent instantiating the XmlSerializer is eliminated.
The other nice thing about this is that you can look at the generated code to see how the serialization/deserialization code is implemented.
The downside is that you need to ensure that you keep the generated code and the code for the class being serialized in sync. You may want to wait until your code stabilizes before switching to the captured code.
sGen in the .Net Framework 2.0
In the .Net Framework 2.0 (Whidbey), there is a new command line tool called sGen that is also accessible from the Visual Studio 2005 IDE in the Build project settings as “Generate serialization assembly”.
Essentially, this automates the list of steps above and creates a corresponding AssemblyName.XmlSerializers.dll where "AssemblyName" corresponds to the name of the assembly that uses the XmlSerializers.
When the XmlSerializer constructor is called, the .Net Framework will look for a corresponding *.XmlSerializers.dll assembly and to load the statically generated serializers.
Its important to realize that this is happening because if you forget to deploy your *.XmlSerializers.dll files, your deployed application will have far worse performance than what you are seeing on your development machines – and if you don’t know about this mechanism, it’ll be hard to figure out why that is.