C#日常优化2-内存泄漏
前言
在.Net Runtime源码提交记录中,看到一个issus,就是有关内存泄漏的,有问题的代码
var jsonDocument = JsonDocument.Parse(json, new JsonDocumentOptions() { AllowTrailingCommas = true });
//仔细观察上面这一行代码,这一行会不会形成内存泄漏正确的代码
using var jsonDocument = JsonDocument.Parse(json, new JsonDocumentOptions() { AllowTrailingCommas = true });
//和有问题代码,相对之前,就增加了using ,在使用完毕之后自动释放性能基准测试
using System;
using System.Text.Json;
using BenchmarkDotNet.Attributes;
[DisassemblyDiagnoser(printSource: true, maxDepth: 3)]
[MemoryDiagnoser]
public class JsonDocumentTest
{
[Params(128, 1024)]
public int Count { get; set; }
private string json;
[GlobalSetup]
public void Setup()
{
json = """
{
"code": "Tst-0003-015",
"name": "测试物料",
"status": 0,
"statusName": "正常",
"specification": "268",
"brand": "",
"unit": "米",
"isReel": false,
"minCount": 0,
"maxCount": 0,
"remark": "",
"paperWeight": 0,
"openness": null,
"paperMo": 0,
"paperLength": 0,
"paperWidth": 0,
"length": 0,
"width": 0,
"height": 0,
"ratio": 0,
"price": 0,
"tonPrice": 0,
"squarePrice": 0,
"id": 2000
}
""";
}
[Benchmark]
public unsafe void Dispose()
{
int sum = 0;
for (int i = 0; i < Count; i++)
{
//使用using管理JsonDocument
using var jsonDocument = JsonDocument.Parse(json, new JsonDocumentOptions() { AllowTrailingCommas = true });
if (jsonDocument is not null)
{
sum += 1;
}
}
}
[Benchmark(Baseline = true)]
public unsafe void NoDispose()
{
int sum = 0;
for (int i = 0; i < Count; i++)
{
//在将json转为JsonDocument后,为进行资源释放,最终在GC在内存不足时触发,释放资源
var jsonDocument = JsonDocument.Parse(json, new JsonDocumentOptions() { AllowTrailingCommas = true });
if (jsonDocument is not null)
{
sum += 1;
}
}
}
}根据上图:
第一轮执行128次,耗时对比使用using比using快了56%,0代GC减少了差不多了31次,内存分配少了98%
第二轮执行1024次,耗时使用using比非using快了10%,0代GC减少了246次,内存分配少了98%,在内存上使用using可以让资源正常回收,减少GC回收的次数,
在两轮测试中,发现使用using和非using在内存上差异是很大的,使用using可以减少内存的占用,主要是资源回收比较及时,减少出发GC回收的次数
秋风
2026-04-02
