Creating an XmlSerializer has a well-known performance cost since .net will generate a temporary helper assembly which requires a compiler call. Additionally, the assembly cannot be unloaded without unloading the hosting application domain causing high memory usage when several XmlSerializer objects are constructed.
Sometimes this assembly-generating process happens in a more indirect manner like the instantiation of a web service proxy class. For example, calling new CrmService() will require an XmlSerializer for the type CrmService which forces .net to generate code, compile and load the assembly. Fortunately, there are alternatives to improve performance and minimize memory usage when creating XmlSerializer objects or instantiating web service proxy classes:
1. Use the pre-generated serializer for CrmService type
If you use a CrmService instance to interact with the CRM server and your project references Microsoft.Crm.SdkTypeProxy.dll, you can add another reference to Microsoft.Crm.SdkTypeProxy.XmlSerializers.dll (you can copy this assembly from the server’s GAC and is also available in the Microsoft Dynamics CRM server installation CD). Because you can make use of the pre-generated serializer then .net will not have to generate a temporary assembly. I experimented this option and noticed a 4-6 second (50% time) performance gain for the CrmService() constructor.
The processor architecture and version of the assemblies Microsoft.Crm.SdkTypeProxy.XmlSerializers.dll must match and Microsoft.Crm.SdkTypeProxy.dll must match in order to be able to use the pre-generated serializers.
Note that if your code is deployed to the CRM server, the assembly Microsoft.Crm.SdkTypeProxy.XmlSerializers.dll is already in the GAC so you will automatically get the benefit of pre-generated serializers for the CrmService type.
Notice that unless you deploy the code to the CRM server, this gain doesn’t apply if you have a web service reference to CrmService instead of an assembly reference to Microsoft.Crm.SdkTypeProxy.dll.
You can copy the serializer assembly from the GAC to your local project directory by running:
copy c:\Windows\assembly\GAC_MSIL\Microsoft.Crm.SdkTypeProxy.XmlSerializers\220.127.116.11__31bf3856ad364e35\Microsoft.Crm.Sdk.dll <your directory>
2. Use the simple XmlSerializer constructors
When you create an XmlSerializer be very conscientious about the constructor you use. Only if you use XmlSerializer(Type) and XmlSerializer(Type, String) your serializer assemblies will be reused until the application domain is unloaded. However, they will still be generated the first time they are needed. When using all the other constructors, there will be a new generated assembly loaded each time you instantiate an XmlSerializer causing memory and performance losses. Alternatively you could implement your own cache for storing XmlSerializers.
3. Generate your own serializers
If you have created types that need to be serialized using XmlSerializer then whenever possible you should generate the serializer assemblies for these types at build time using tools such as sgen or xgen. This way you totally avoid .net generating temporary assemblies on the fly.
As an example, if you created MyType in MyAssembly.dll and you know this type will be serialized by an XmlSerializer you should run:
Sgen.exe /t:MyType /a:MyAssembly.dll
This will generate the serializer assembly MyAssembly.XmlSerializers.dll which should be added to the current project or to the GAC.
- Documentation about the different XmlSerializer constructors from MSDN: http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx
- Sgen documentation to generate serializers at build time: http://msdn.microsoft.com/en-us/library/bk3w6240(VS.80).aspx