Dynamics CRM functionality is now a part of Dynamics 365, a suite of intelligent business applications. This blog covers the Dynamics 365 Customer Engagement apps and all supported versions of Dynamics CRM.

Boost performance with Pre-generated XmlSerializers

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.

Some considerations:

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:

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.

I find your tutorial very useful, I was not expecting to see such a huge benefit! (~12 seconds in your case).

Unfortunatelly you’d have to generate your own CrmService proxy which has the disadvantages you pointed out. If you could use the SdkTypeProxy and SdkTypeProxy.XmlSerializers that are shipped woth the product you’d only have to do step 10.

Looking at the directory that contains the temporary assemblies again I only see 1 temporary assembly which judging by the times in Test Run 2 would indicate that the Web Reference is using the pre-generated assembly correctly.

According your blog post as long as the Microsoft.Crm.SdkTypeProxy.XmlSerializers.dll is in the GAC and you are using the same processor architecture and version than the pre-compiled assembly should see a speed increase because it will use the XmlSerializers.dll. This is clearly not the case if you look at the times it takes to instantiate the first CrmService and the temporary files been generated.

The only reason I know for which this would not work is if the assembly Microsoft.Crm.SdkTypeProxy.XmlSerializers.dll was generated against a different version of the assembly Microsoft.Crm.SdkTypeProxy.dll that you are using.

Microsoft.Crm.SdkTypeProxy.XmlSerializers.dll remembers the exact assembly Id of its parent assembly, a way to find out whether they match is to disassemble both assemblies. If both of these assemblies are taken from the same source then they should come from the same build so the assembly Id should match.