0

I'm creating a HttpPost endpoint for an API that takes an XML body, does some processing on the data received, sends a request to an external API, and returns the data from the external API in XML format.

During the process I serialize and deserialize to and from multiple different classes. The problem I'm having is that the constructor for these serializers is taking a relatively long time to load, and having an impact on the response times of my API.

Here is the current code for serialization/deserialization:

public static T DeserializeObject<T>(Stream objectStream)
{
    try
    {
        XmlSerializer serializer = new XmlSerializer(typeof(T));
        using (StreamReader stream = new StreamReader(objectStream))
        {
            return (T)serializer.Deserialize(stream);
        }
    }
    catch (Exception ex)
    {
        HttpResponseMessage message = new HttpResponseMessage(HttpStatusCode.InternalServerError);
        message.Content = new StringContent("Error deserializing type: " + typeof(T).ToString() + Environment.NewLine
                                                + ex.Message
                                                + (ex.InnerException != null ? Environment.NewLine + ex.InnerException.Message : string.Empty));
        throw new HttpResponseException(message);
    }
}

public static string SerializeObject<T>(T objectToSerialize)
{
    try
    {
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));

        using (MemoryStream stream = new MemoryStream())
        using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8))
        {
            xmlSerializer.Serialize(writer, objectToSerialize);

            return Encoding.UTF8.GetString(stream.ToArray());
        }
    }
    catch (Exception ex)
    {
        HttpResponseMessage message = new HttpResponseMessage(HttpStatusCode.InternalServerError);
        message.Content = new StringContent("Error serializing type: " + typeof(T).ToString() + Environment.NewLine
                                                + ex.Message
                                                + (ex.InnerException != null ? Environment.NewLine + ex.InnerException.Message : string.Empty));
        throw new HttpResponseException(message);
    }
}

I have some fairly complex classes that are being serialized to, but that is unavoidable due to having to send a request to an external API. I'm also locked in to using XML due to third parties integrating with the API

How can I improve the performance of the XML serializer and speed up the response time of my API?

Luke4792
  • 455
  • 5
  • 19
  • 1
    You need out find out exactly where the delays are coming from. So I would start by using a sniffer like wireshark or fiddler to determine the delays. You also want to find out the amount of data the is being transferred. You may be able to gzip the response to reduce the amount of data. There may be a virus checker on the firewall that is checking the contents of the data. So you may want to try on you home computer to compare response time with no checker. – jdweng Nov 08 '19 at 16:05
  • I've profiled my program and determined a lot of time is being lost to the constructor of the XMLSerialiser class. – Luke4792 Nov 08 '19 at 16:16
  • From the source code (https://referencesource.microsoft.com/#System.Xml/System/Xml/Serialization/XmlSerializer.cs,292c7197dcb706a1) it looks like it is calling Reflection which is the reason for the long time. The constructor is calling Serialization(type, null [this is the string namespace]). – jdweng Nov 08 '19 at 16:44
  • Use [`Sgen.exe`](https://learn.microsoft.com/en-us/dotnet/standard/serialization/xml-serializer-generator-tool-sgen-exe) to create precompiled `XmlSerializer` assemblies. See: [How to make XML deserialization faster?](https://stackoverflow.com/a/8145222/3744182) and [Generating an Xml Serialization assembly as part of my build](https://stackoverflow.com/a/8798289/3744182). – dbc Nov 08 '19 at 17:16
  • Also, you can serialize directly to a string without the intermediate `MemoryStream`. See [this answer](https://stackoverflow.com/a/3862106/3744182) to [Serializing an object as UTF-8 XML in .NET](https://stackoverflow.com/q/3862063/3744182) and also [XmlWriter encoding UTF-8 using StringWriter in C#](https://stackoverflow.com/q/42583299/3744182). – dbc Nov 08 '19 at 17:23
  • But `Sgen.exe` is a little tricky to use and deploy so you should test it out before we mark this as a duplicate. (Another option would be to generate an initial `XmlSerializer` for common types `T` in a background thread during startup. Once generated, .Net caches it for the duration of the `AppDomain`.) – dbc Nov 08 '19 at 17:29
  • Thanks for the suggestions, I'll try them out and see how it goes. – Luke4792 Nov 08 '19 at 17:41

0 Answers0