C# 批量反序列化大量JSON文件的高效实现方案咨询
优化方案总览
- 替换单线程遍历为并行处理,充分利用多核CPU性能
- 复用JSON序列化器实例,避免重复创建实例的冗余开销
- 选择性能更优的JSON序列化库,或调整序列化配置减少不必要的校验损耗
- 优化IO读取逻辑,减少文件遍历和读取的额外开销
- 预分配集合容量,避免动态扩容的性能损耗
优化后代码示例
基于原有Newtonsoft.Json的优化版本
无需更换序列化库,仅优化执行逻辑即可获得数倍性能提升:
// 流式枚举文件路径,大数量场景下比GetFiles启动速度更快 var files = Directory.EnumerateFiles(@"C:\Data","*.json").ToList(); // 并行场景下使用线程安全的ConcurrentBag存储结果,避免加锁开销 var resultBag = new ConcurrentBag<ParsedData>(); // 全局复用序列化器实例,无需每次循环创建 var jsonSerializer = new JsonSerializer(); var dt1 = DateTime.Now; // 并行处理文件,可根据存储介质调整并行度:SSD可设为CPU核心数的2-4倍,HDD建议不超过核心数2倍 Parallel.ForEach(files, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount * 2 }, file => { using var streamReader = File.OpenText(file); var data = (ParsedData)jsonSerializer.Deserialize(streamReader, typeof(ParsedData)); resultBag.Add(data); }); // 按需转为List使用 var list = resultBag.ToList(); var dt2 = DateTime.Now; Console.WriteLine((dt2 - dt1).TotalMilliseconds);
更高性能的System.Text.Json版本
更换为.NET官方内置的System.Text.Json序列化库,性能比Newtonsoft.Json高30%以上:
using System.Text.Json; var files = Directory.EnumerateFiles(@"C:\Data","*.json").ToList(); var resultBag = new ConcurrentBag<ParsedData>(); // 全局配置序列化选项,关闭不必要的校验提升性能 var jsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, AllowTrailingCommas = true, ReadCommentHandling = JsonCommentHandling.Skip }; var dt1 = DateTime.Now; Parallel.ForEach(files, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount * 2 }, file => { var fileBytes = File.ReadAllBytes(file); var data = JsonSerializer.Deserialize<ParsedData>(fileBytes, jsonOptions); if(data != null) resultBag.Add(data); }); var list = resultBag.ToList(); var dt2 = DateTime.Now; Console.WriteLine((dt2 - dt1).TotalMilliseconds);
额外优化建议
- 如果JSON文件普遍偏小,可以批量读取多个文件到内存后再反序列化,减少IO调用次数
- 给
ParsedData的属性添加明确的序列化属性映射,避免序列化器反射匹配属性的开销 - 如果磁盘是HDD,不要设置过高的并行度,避免随机IO过高反而拖慢整体速度
内容的提问来源于stack exchange,提问作者Hossein
相关产品推荐
相关产品推荐

