Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
215 views
in Technique[技术] by (71.8m points)

c# - Performance optimizing use of generated XmlSerializer class

We have a few XML files that are being read by our applications. The XML format is fixed, and thus we can read them very easily with XmlSerializer.

I use this code to read the XML files and convert them to classes:

public static T FromXml<T>(this string xml) where T : class
{
    if (string.IsNullOrEmpty(xml))
    {
        return default(T);
    }

    XmlSerializer xmlserializer = new XmlSerializer(typeof(T));

    XmlTextReader textReader = new XmlTextReader(new StringReader(xml));
    textReader.Normalization = false;

    XmlReaderSettings settings = new XmlReaderSettings();

    T value;

    using (XmlReader reader = XmlReader.Create(textReader, settings))
    {
        value = (T)xmlserializer.Deserialize(reader);
    }

    return value;
}

However, there are some performance issues. When calling this code for the first time a specific type for T is used, the XmlSerializer generates a Project.XmlSerializer.dll file.

This is fine, but costs some precious milliseconds (about 900ms in my case). This can be circumvented by generating that assembly on forehand, using the XML Serializer Generator (sgen). This brings down the time to about half. Primarily due to the reading and reflection of the assembly.

I want to optimize this further, by bringing the XmlSerializer classes inside the assembly the actual classes are in, but I can't find a way to let XmlSerializer know not to read an external assembly, but use the serializer from the current assembly.

Any thoughts how to do this or an alternative way to make this work? (I can't pre-load them since most of the serialized classes are used at start-up)


The analysis using ANTS Profiler (metrics from other machine, but same pattern):

enter image description here

Plain. Most of the time (300ms + 400ms = 700ms) is lost in generating and loading the XmlSerializer assembly.

enter image description here

With sgen generated assembly. Most of the time (336ms) is lost in loading the XmlSerializer assembly.

enter image description here

When including the actual source of the assembly inside the project, and calling the serializer directly, the action goes down to 456ms (was 1s in first, 556ms in second).

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Unless you are doing the serialization at the very app startup, one way would be to force CLR to load and even compile whatever classes you're using ahead of time, possibly in a thread which would run in background as soon as you've started your app.

Something like, for example:

foreach (Assembly a in assembliesThatShouldBeCompileed)
    foreach (Type type in a.GetTypes())
        if (!type.IsAbstract && type.IsClass)
        {
            foreach (MethodInfo method in type.GetMethods(
                                BindingFlags.DeclaredOnly |
                                BindingFlags.NonPublic |
                                BindingFlags.Public |
                                BindingFlags.Instance |
                                BindingFlags.Static))
            {
                if (method.ContainsGenericParameters || 
                    method.IsGenericMethod || 
                    method.IsGenericMethodDefinition)
                    continue;

                if ((method.Attributes & MethodAttributes.PinvokeImpl) > 0)
                    continue;

                System.Runtime.CompilerServices
                   .RuntimeHelpers.PrepareMethod(method.MethodHandle);
            }
        }

It's strange, however, that your profiling seems to indicate that there is not much difference if the SGEN'd code is in a separate assembly, while loading seems to be the bottleneck. I wonder how the graph looks like for the case where they are in the same assembly?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...