JSON.NET ANY ContractResolver 导致性能不佳

在对非常高吞吐量的应用程序进行性能测试期间,我们发现 JSON.NET 的ContractResolver. 不幸的是,当您指定一个时ContractResolver,性能似乎变得难以忍受,包括DefaultContractResolver

寻求其他专家的建议,以获取有关如何获得性能而不锁定 CPU 并占用不合理时间的任何建议。现在,由于这个问题,我们看到性能下降了 87%(有任何ContractResolver定义的每秒 80 个请求,没有ContractResolver 定义的每秒 600 个请求。

测试运行的输出是:

默认解析器: Time elapsed 3736 milliseconds

NoOp 解析器: Time elapsed 4150 milliseconds

无解析器: Time elapsed 8 milliseconds

蛇盒: Time elapsed 4753 milliseconds

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


慕森王
浏览 185回答 1
1回答

MMTTMM

看起来好像ContractResolver需要反射,并且如果坚持下去就会缓存对象类型。将 存储ContractResolver在全局范围内会大大改变时间:默认解析器: Time elapsed 10 millisecondsNoOp 解析器: 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{&nbsp; &nbsp; public class Person&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; public string Name { get; set; }&nbsp; &nbsp; &nbsp; &nbsp; public DateTime DateOfBirth { get; set; }&nbsp; &nbsp; &nbsp; &nbsp; public bool EatsMeat { get; set; }&nbsp; &nbsp; &nbsp; &nbsp; public decimal YearlyHouseholdIncome { get; set; }&nbsp; &nbsp; &nbsp; &nbsp; public List<Car> CarList { get; set; }&nbsp; &nbsp; }&nbsp; &nbsp; public class Car&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; public string Make { get; set; }&nbsp; &nbsp; &nbsp; &nbsp; public string Model { get; set; }&nbsp; &nbsp; &nbsp; &nbsp; public int Year { get; set; }&nbsp; &nbsp; }&nbsp; &nbsp; public class NoOpNamingStrategy : NamingStrategy&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; public NoOpNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; base.ProcessDictionaryKeys = processDictionaryKeys;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; base.OverrideSpecifiedNames = overrideSpecifiedNames;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; public NoOpNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames, bool processExtensionDataNames) : this(processDictionaryKeys, overrideSpecifiedNames)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; base.ProcessExtensionDataNames = processExtensionDataNames;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; public NoOpNamingStrategy()&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; protected override string ResolvePropertyName(string name)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return name;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; [TestClass]&nbsp; &nbsp; public class SerializationTest&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; public static Person p { get; set; } = new Person&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Name = "Foo Bar",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DateOfBirth = new DateTime(1970, 01, 01),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EatsMeat = true,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; YearlyHouseholdIncome = 47333M,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CarList = new List<Car>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new Car&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Make = "Honda",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Model = "Civic",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Year = 2019&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; &nbsp; &nbsp; public static IContractResolver Default { get; set; } = new DefaultContractResolver();&nbsp; &nbsp; &nbsp; &nbsp; public static IContractResolver NoOp { get; set; } = new DefaultContractResolver&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NamingStrategy = new NoOpNamingStrategy()&nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; &nbsp; &nbsp; public static IContractResolver SnakeCase { get; set; } = new DefaultContractResolver&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NamingStrategy = new SnakeCaseNamingStrategy()&nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; &nbsp; &nbsp; public static IContractResolver ThirdParty { get; set; } = new SnakeCaseContractResolver();&nbsp; &nbsp; &nbsp; &nbsp; public const int ITERATIONS = 1000;&nbsp; &nbsp; &nbsp; &nbsp; [TestMethod]&nbsp; &nbsp; &nbsp; &nbsp; public void TestSnakeCase()&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var sw = new Stopwatch();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sw.Start();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (var i = 0; i < ITERATIONS; i++)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var str = JsonConvert.SerializeObject(p, new JsonSerializerSettings&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ContractResolver = SnakeCase&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sw.Stop();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var elapsed = sw.ElapsedMilliseconds;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Debug.WriteLine($"Time elapsed {elapsed} milliseconds");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; [TestMethod]&nbsp; &nbsp; &nbsp; &nbsp; public void TestNoResolver()&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var sw = new Stopwatch();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sw.Start();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (var i = 0; i < ITERATIONS; i++)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var str = JsonConvert.SerializeObject(p);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sw.Stop();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var elapsed = sw.ElapsedMilliseconds;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Debug.WriteLine($"Time elapsed {elapsed} milliseconds");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; [TestMethod]&nbsp; &nbsp; &nbsp; &nbsp; public void TestDefaultResolver()&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var sw = new Stopwatch();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sw.Start();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (var i = 0; i < ITERATIONS; i++)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var str = JsonConvert.SerializeObject(p, new JsonSerializerSettings&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ContractResolver = Default&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sw.Stop();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var elapsed = sw.ElapsedMilliseconds;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Debug.WriteLine($"Time elapsed {elapsed} milliseconds");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; [TestMethod]&nbsp; &nbsp; &nbsp; &nbsp; public void TestThirdPartySnakeResolver()&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var sw = new Stopwatch();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sw.Start();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (var i = 0; i < ITERATIONS; i++)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var str = JsonConvert.SerializeObject(p, new JsonSerializerSettings&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ContractResolver = ThirdParty&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sw.Stop();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var elapsed = sw.ElapsedMilliseconds;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Debug.WriteLine($"Time elapsed {elapsed} milliseconds");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; [TestMethod]&nbsp; &nbsp; &nbsp; &nbsp; public void TestNoOpResolver()&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var sw = new Stopwatch();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sw.Start();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (var i = 0; i < ITERATIONS; i++)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var str = JsonConvert.SerializeObject(p, new JsonSerializerSettings&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ContractResolver = NoOp&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sw.Stop();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var elapsed = sw.ElapsedMilliseconds;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Debug.WriteLine($"Time elapsed {elapsed} milliseconds");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}
打开App,查看更多内容
随时随地看视频慕课网APP