为了账号安全,请及时绑定邮箱和手机立即绑定

JSON.NET ANY ContractResolver 导致性能不佳

JSON.NET ANY ContractResolver 导致性能不佳

C#
慕森王 2021-11-07 19:21:43
在对非常高吞吐量的应用程序进行性能测试期间,我们发现 JSON.NET 的ContractResolver. 不幸的是,当您指定一个时ContractResolver,性能似乎变得难以忍受,包括DefaultContractResolver寻求其他专家的建议,以获取有关如何获得性能而不锁定 CPU 并占用不合理时间的任何建议。现在,由于这个问题,我们看到性能下降了 87%(有任何ContractResolver定义的每秒 80 个请求,没有ContractResolver 定义的每秒 600 个请求。测试运行的输出是:默认解析器: Time elapsed 3736 millisecondsNoOp 解析器: Time elapsed 4150 milliseconds无解析器: Time elapsed 8 milliseconds蛇盒: Time elapsed 4753 milliseconds第三方(SnakeCase.JsonNet): Time elapsed 3881 milliseconds
查看完整描述

1 回答

?
MMTTMM

TA贡献1869条经验 获得超4个赞

看起来好像ContractResolver需要反射,并且如果坚持下去就会缓存对象类型。将 存储ContractResolver在全局范围内会大大改变时间:


默认解析器: Time elapsed 10 milliseconds


NoOp 解析器: Time elapsed 7 milliseconds


无解析器: Time elapsed 7 milliseconds


蛇盒: Time elapsed 178 milliseconds


第三方(SnakeCase.JsonNet): Time elapsed 10 milliseconds


更新测试代码:


using System;

using System.Collections.Generic;

using System.Diagnostics;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using Newtonsoft.Json;

using Newtonsoft.Json.Serialization;

using SnakeCase.JsonNet;


namespace Anonymous.Public.Namespace

{

    public class Person

    {

        public string Name { get; set; }

        public DateTime DateOfBirth { get; set; }

        public bool EatsMeat { get; set; }

        public decimal YearlyHouseholdIncome { get; set; }


        public List<Car> CarList { get; set; }

    }


    public class Car

    {

        public string Make { get; set; }

        public string Model { get; set; }

        public int Year { get; set; }

    }

    public class NoOpNamingStrategy : NamingStrategy

    {

        public NoOpNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames)

        {

            base.ProcessDictionaryKeys = processDictionaryKeys;

            base.OverrideSpecifiedNames = overrideSpecifiedNames;

        }


        public NoOpNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames, bool processExtensionDataNames) : this(processDictionaryKeys, overrideSpecifiedNames)

        {

            base.ProcessExtensionDataNames = processExtensionDataNames;

        }


        public NoOpNamingStrategy()

        {

        }


        protected override string ResolvePropertyName(string name)

        {

            return name;

        }

    }


    [TestClass]

    public class SerializationTest

    {

        public static Person p { get; set; } = new Person

        {

            Name = "Foo Bar",

            DateOfBirth = new DateTime(1970, 01, 01),

            EatsMeat = true,

            YearlyHouseholdIncome = 47333M,

            CarList = new List<Car>

            {

                new Car

                {

                    Make = "Honda",

                    Model = "Civic",

                    Year = 2019

                }

            }

        };


        public static IContractResolver Default { get; set; } = new DefaultContractResolver();


        public static IContractResolver NoOp { get; set; } = new DefaultContractResolver

        {

            NamingStrategy = new NoOpNamingStrategy()

        };


        public static IContractResolver SnakeCase { get; set; } = new DefaultContractResolver

        {

            NamingStrategy = new SnakeCaseNamingStrategy()

        };


        public static IContractResolver ThirdParty { get; set; } = new SnakeCaseContractResolver();


        public const int ITERATIONS = 1000;


        [TestMethod]

        public void TestSnakeCase()

        {

            var sw = new Stopwatch();

            sw.Start();

            for (var i = 0; i < ITERATIONS; i++)

            {

                var str = JsonConvert.SerializeObject(p, new JsonSerializerSettings

                {

                    ContractResolver = SnakeCase

                });

            }


            sw.Stop();

            var elapsed = sw.ElapsedMilliseconds;

            Debug.WriteLine($"Time elapsed {elapsed} milliseconds");

        }


        [TestMethod]

        public void TestNoResolver()

        {

            var sw = new Stopwatch();

            sw.Start();

            for (var i = 0; i < ITERATIONS; i++)

            {

                var str = JsonConvert.SerializeObject(p);

            }


            sw.Stop();

            var elapsed = sw.ElapsedMilliseconds;

            Debug.WriteLine($"Time elapsed {elapsed} milliseconds");

        }


        [TestMethod]

        public void TestDefaultResolver()

        {

            var sw = new Stopwatch();

            sw.Start();

            for (var i = 0; i < ITERATIONS; i++)

            {

                var str = JsonConvert.SerializeObject(p, new JsonSerializerSettings

                {

                    ContractResolver = Default

                });

            }


            sw.Stop();

            var elapsed = sw.ElapsedMilliseconds;

            Debug.WriteLine($"Time elapsed {elapsed} milliseconds");

        }


        [TestMethod]

        public void TestThirdPartySnakeResolver()

        {

            var sw = new Stopwatch();

            sw.Start();

            for (var i = 0; i < ITERATIONS; i++)

            {

                var str = JsonConvert.SerializeObject(p, new JsonSerializerSettings

                {

                    ContractResolver = ThirdParty

                });

            }


            sw.Stop();

            var elapsed = sw.ElapsedMilliseconds;

            Debug.WriteLine($"Time elapsed {elapsed} milliseconds");

        }


        [TestMethod]

        public void TestNoOpResolver()

        {

            var sw = new Stopwatch();

            sw.Start();

            for (var i = 0; i < ITERATIONS; i++)

            {

                var str = JsonConvert.SerializeObject(p, new JsonSerializerSettings

                {

                    ContractResolver = NoOp

                });

            }


            sw.Stop();

            var elapsed = sw.ElapsedMilliseconds;

            Debug.WriteLine($"Time elapsed {elapsed} milliseconds");

        }

    }

}


查看完整回答
反对 回复 2021-11-07
  • 1 回答
  • 0 关注
  • 184 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信