- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在对吞吐量非常高的应用程序进行性能测试时,我们发现 JSON.NET 的 ContractResolver
存在问题。不幸的是,当您指定 ContractResolver
时,性能变得难以忍受,包括 DefaultContractResolver
寻求其他专家的建议,了解有关如何提高性能而不锁定 CPU 和占用不合理时间的任何建议。现在,由于这个问题,我们发现性能降低了 87%(定义任何 ContractResolver
时每秒 80 个请求,没有定义 ContractResolver
时每秒 600 个请求定义。
测试运行的输出是:
默认解析器:耗时 3736 毫秒
NoOp 解析器:耗时 4150 毫秒
无解析器:已用 8 毫秒
SnakeCase:耗时 4753 毫秒
第三方 (SnakeCase.JsonNet):耗时 3881 毫秒
强调这一点的测试如下:
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 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 = new DefaultContractResolver
{
NamingStrategy = new SnakeCaseNamingStrategy()
}
});
}
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 = new DefaultContractResolver()
});
}
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 = new SnakeCaseContractResolver()
});
}
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 = new DefaultContractResolver
{
NamingStrategy = new NoOpNamingStrategy()
}
});
}
sw.Stop();
var elapsed = sw.ElapsedMilliseconds;
Debug.WriteLine($"Time elapsed {elapsed} milliseconds");
}
}
}
最佳答案
看起来好像 ContractResolver
需要反射,如果保留的话将缓存对象类型。在全局范围内存储 ContractResolver
会大大改变时间:
默认解析器:耗时 10 毫秒
NoOp 解析器:7 毫秒过去的时间
无解析器:耗时 7 毫秒
SnakeCase:耗时 178 毫秒
第三方 (SnakeCase.JsonNet):耗时 10 毫秒
更新的测试代码:
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");
}
}
}
关于c# - JSON.NET ANY ContractResolver 导致性能不佳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51603054/
我有一个 .NET Core Web Api 2.1 应用程序,我在其中仅序列化客户端请求的属性。 示例:GET orders/1?select=Id,TotalAmount 示例:GET order
我希望每个没有指定 JsonPropertyAttribute 的属性都遵循自定义协定。但如果它被指定,那么这正是它应该是的。 但是如果我有一个映射属性并且正在使用自定义契约解析器,那么契约解析器可以
我正在尝试使用自定义转换器修改对象类型,如 here 所述, 连同 CamelCasePropertyNamesContractResolver . 所以转换器是这样的(这里什么都不做): class
//这是 Camel 肠衣 services.AddMvcCore() .AddJsonOptions(options => { opt
我需要将有关自定义异常类型的信息从 WebApi Web 服务传递到客户端。为此,我尝试使用 Json.Net 序列化程序 + CustomContractResolver 来控制发送给客户端的内容。
我想从自定义对象创建一个模式。自定义对象有一些字符串属性,这些属性被架构化为类型 String|Null。我如何修改 JSonSchemaGenerator 以将字符串转换为类型 String 而不是
我使用 JSON.net 已经有一段时间了。我已经编写了自定义转换器和自定义契约(Contract)解析器(通常来自修改 S.O. 和 Newtonsoft 网站上的示例),它们工作正常。 挑战在于,
我有一些带有本地化文本的 .NET 类;即英语文本,相应的西类牙语文本等。我们有一个看起来像这样的 Locale 类: class Locale { int Id; string Ab
在对吞吐量非常高的应用程序进行性能测试时,我们发现 JSON.NET 的 ContractResolver 存在问题。不幸的是,当您指定 ContractResolver 时,性能变得难以忍受,包括
这是我到目前为止所得到的。感谢Brian Rodgers : public class JsonSerializeTest { [Fact] public void deseriali
我有这个 JSON: {"firstName": "John","lastName": "Doe"} 这个 JSON.NET 契约(Contract)解析器: public class CustomC
我的要求是在反序列化期间使用 JsonProperty 并在序列化期间忽略 JsonProperty。我的模型, [JsonConverter(typeof(JsonPathConverter))]
在 asp.net web api 中,我想序列化我的 C# 属性(pascal 大小写),任何名称为“Links”的属性都应序列化为“_links”,其余属性应序列化为自身 Camel 肠衣。 到目
如果我使用 JsonConvert.SerializeObject 序列化一个对象,指定自定义契约解析器的方法是这样的: var serializerSettings = new JsonSerial
我是一名优秀的程序员,十分优秀!