使用BenchmarkDotNet时,如何对大JSON反序列化做LOH基准测试?
如何用BenchmarkDotNet的MemoryDiagnoser监控大对象堆(LOH)状态
当然可以!其实你已经启用的MemoryDiagnoser本身就支持LOH相关的性能统计,只是需要明确怎么配置和解读输出数据,我之前做大型JSON反序列化的基准测试时也研究过这个点,分享下具体方法:
1. 确保MemoryDiagnoser的正确配置
首先确认你已经在基准测试类上添加了[MemoryDiagnoser]特性(如果需要更详细的GC代信息,可以加上displayGenColumns: true参数):
[MemoryDiagnoser(displayGenColumns: true)] public class JsonDeserializationBenchmarks { // 你的基准测试方法:从String反序列化 [Benchmark] public MyLargeModel DeserializeFromString() { return JsonSerializer.Deserialize<MyLargeModel>(LargeJsonString); } // 你的基准测试方法:从Stream反序列化 [Benchmark] public MyLargeModel DeserializeFromStream() { using var stream = new MemoryStream(Encoding.UTF8.GetBytes(LargeJsonString)); return JsonSerializer.Deserialize<MyLargeModel>(stream); } }
2. 解读输出中的LOH相关数据
- .NET Framework环境:LOH中的对象属于Gen 2,所以输出里的
Gen 2列统计的回收次数,以及Allocated列的总分配量,就能间接反映LOH的压力——如果Gen 2回收频繁,大概率是LOH有大量大对象分配。 - .NET Core 3.0+/.NET 5+环境:BenchmarkDotNet的
MemoryDiagnoser会直接在输出中显示Large Object Heap Allocated列,这个数值就是测试过程中LOH的总分配量,非常直观。
举个输出示例(.NET 6环境):
| Method | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated | Large Object Heap Allocated | |---------------------- |---------:|---------:|---------:|-------:|-------:|------:|----------:|----------------------------:| | DeserializeFromString | 123.4 ms | 2.34 ms | 2.19 ms | - | - | 1 | 456.7 MB | 389.2 MB | | DeserializeFromStream | 98.7 ms | 1.87 ms | 1.75 ms | - | - | 0 | 321.5 MB | 256.3 MB |
这里的Large Object Heap Allocated就是你要关注的LOH核心指标,能直接对比两种反序列化方式在LOH上的分配差异。
3. 额外的进阶配置
如果需要更深入的LOH分析,比如对象的存活时长、碎片化情况,可以结合以下方式:
- 启用BenchmarkDotNet的
[GcDiagnoser]特性,它会提供更详细的GC事件数据,包括LOH的分配和回收细节。 - 配合Visual Studio的内存快照工具,在基准测试运行时捕获内存状态,直观查看LOH中的对象分布。
这样你就能全面对比两种反序列化方式在LOH上的性能表现了!
内容的提问来源于stack exchange,提问作者Cholesterol
相关产品推荐
相关产品推荐

