使用 DataContract 反序列化为枚举时如何优化 ServiceStack.Text 性能

How to optimize ServiceStack.Text performance when deserializing to enums with DataContract

在将枚举值反序列化为具有 DataContract and EnumMember 属性集的 .Net 枚举时,是否有优化 ServiceStack.Text(版本 5.4.0)性能的方法?我想使用 EnumMember 属性来定义序列化名称,但不幸的是 ServiceStack.Text 似乎需要大约三倍的时间来使用此方法进行反序列化,而不是基于普通枚举成员名称进行反序列化。

例如,考虑这个简单的 C# 测试程序:

using ServiceStack;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.Serialization;
using System.Text;

namespace ServiceStackPerformance
{
    public class Program
    {
        [DataContract]
        enum DataContractEnum
        {
            [EnumMember(Value = "first")]
            First = 0,
            [EnumMember(Value = "second")]
            Second = 1,
        }

        enum PlainEnum
        {
            first = 0,
            second = 1,
        }

        [DataContract]
        class DataContractEnumList
        {
            [DataMember(Name = "values")]
            public List<DataContractEnum> Values { get; set; }
        }

        [DataContract]
        class PlainEnumList
        {
            [DataMember(Name = "values")]
            public List<PlainEnum> Values { get; set; }
        }

        static void Main(string[] args)
        {
            int size = 100000;
            string test = GenerateTestString(size);
            var stopwatch = new Stopwatch();

            stopwatch.Start();
            var dataContractEnumList = test.FromJson<DataContractEnumList>();
            var dataContractMs = stopwatch.ElapsedMilliseconds;

            stopwatch.Restart();
            var plainType = test.FromJson<PlainEnumList>();
            var plainMs = stopwatch.ElapsedMilliseconds;

            Console.WriteLine($"Deserializing input of size {2*size+1} to data contract enum took {dataContractMs} ms.");
            Console.WriteLine($"Deserializing input of size {2*size+1} to simple enum took {plainMs} ms.");
        }

        private static string GenerateTestString(int size)
        {
            var builder = new StringBuilder(10*size);
            builder.Append("{\"values\":[");
            for ( int i = 0; i < size; i++)
            {
                builder.Append("\"first\",\"second\",");
            }
            builder.Append("\"first\"]}");

            return builder.ToString();
        }
    }
}

输出如下:

Deserializing input of size 200001 to data contract enum took 3520 ms.
Deserializing input of size 200001 to simple enum took 1131 ms.

是否可以启用任何缓存或其他性能优化来避免减速?

使用缓存枚举信息的 this commit and deserialization of Enums in this commit 应该改进 [EnumMember] 枚举的性能。

此更改适用于现在 available on MyGet 的 v5.4.1。