gpt4 book ai didi

c# - Json.NET 是否缓存类型的序列化信息?

转载 作者:IT王子 更新时间:2023-10-29 04:34:47 25 4
gpt4 key购买 nike

在 .NET 世界中,当谈到对象序列化时,通常会在运行时检查对象的字段和属性。为这项工作使用反射通常很慢,并且在处理大量对象时是不可取的。另一种方法是使用 IL emit 或构建表达式树,它们比反射提供显着的性能增益。后者是大多数现代图书馆在处理序列化时选择的。但是,在运行时构建和发出 IL 需要时间,只有缓存此信息并将其重新用于相同类型的对象,投资才能得到返回。

在使用Json.NET时,我不清楚使用的是上述哪种方法,如果确实使用了后者,是否使用了缓存。

例如,当我这样做时:

JsonConvert.SerializeObject(new Foo { value = 1 });

Json.NET 是否构建 Foo 的成员访问信息并缓存以备日后重用?

最佳答案

是的,确实如此。Json.NET 在其 IContractResolver 中缓存类型序列化信息。类(class) DefaultContractResolverCamelCasePropertyNamesContractResolver .除非您指定自定义契约(Contract)解析器,否则此信息将被缓存并重复使用。

对于 DefaultContractResolver,在内部维护一个全局静态实例,只要应用程序未指定其自己的契约(Contract)解析器,Json.NET 就会使用该实例。另一方面,CamelCasePropertyNamesContractResolver 维护所有实例共享的静态表。 (我认为不一致是由遗留问题引起的;有关详细信息,请参阅 here。)

这两种类型都设计为完全线程安全的,因此线程之间的共享应该不是问题。

如果您选择实现和实例化您自己的契约(Contract)解析器,那么类型信息只有在您缓存和重用契约(Contract)解析器实例本身时才会被缓存和重用。因此,Newtonsoft recommends :

For performance you should create a contract resolver once and reuse instances when possible. Resolving contracts is slow and implementations of IContractResolver typically cache contracts.

如果内存消耗是一个问题,并且出于任何原因您需要最小化缓存合约永久占用的内存,您可以构建自己的 DefaultContractResolver 本地实例(或一些自定义子类),使用它进行序列化,然后立即删除对它的所有引用,例如:

public class JsonExtensions
{
public static string SerializeObjectNoCache<T>(T obj, JsonSerializerSettings settings = null)
{
settings = settings ?? new JsonSerializerSettings();
bool reset = (settings.ContractResolver == null);
if (reset)
// To reduce memory footprint, do not cache contract information in the global contract resolver.
settings.ContractResolver = new DefaultContractResolver();
try
{
return JsonConvert.SerializeObject(obj, settings);
}
finally
{
if (reset)
settings.ContractResolver = null;
}
}
}

如果您正在使用 CamelCasePropertyNamesContractResolver,请切换到带有适当 naming strategyDefaultContractResolver比如:

settings.ContractResolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy() };

大部分缓存的合约内存( but not all )最终会被垃圾回收。当然,通过这样做,序列化性能可能会受到很大影响。 (一些包含有关例如 enum 类型和数据协定属性的反射(reflect)信息的表是全局共享的,不会被回收。)

有关更多信息,请参阅 Newtonsoft 的 Performance Tips: Reuse Contract Resolver .

关于c# - Json.NET 是否缓存类型的序列化信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33557737/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com