所以似乎没有人做过与我的问题相关的事情,我已经进行了自己的测试,现在我不想分享我的结果。希望他们真的很有帮助。
起初我想说我对一些结果感到非常震惊和惊讶。
首先是我的测试机配置:
- 配备 2.40 GHz 英特尔酷睿 i5-6200 CPU 的 HP Probook 450 G3 笔记本电脑
- 8 GB 内存
- 256MB SSD Patriot Ignite M2,高达 560MB/s 读取和 320MB/s 写入 IO
- 希捷 1000 GB SATA 硬盘
- Windows 10 专业版 x64 操作系统
测试非常简单:有一个 json 字符串,它的大小存储在一个 4.54 kB 的文件中。我运行 100 个测试,每个测试创建 1000 个指定类型的对象(动态/JToken/JContainer)。在每次测试期间,我都会计算分配这 1000 个对象的实际内存量以及将 json-string 解析为指定对象类型所需的时间。完成所有测试后,我计算每个测试集的平均已用内存量和平均时间。通过基于公式for 0 < i < n, S += SUM(i), a = S/n 的简单算法计算的平均计数器,其中S - 所有计数器的总和,n - 测试数量 (100),a - 平均计数器。内存使用由Process 和GC 统计
现在最有趣的部分 (IMO) - 我的基准测试结果 :)
首先我使用Newtonsoft.JSON 内置方法JToken.Parse() 和JContainer.Parse() 运行测试。这两个集合都产生了与预期相同的结果(因为JContainer 是来自JToken 的嵌套类型):
JToken/JContainer
平均内存使用:25.7 MB
平均解析时间:223 毫秒
很简单。现在我使用 JsonConver.Deserialize<T>(string json) 方法运行测试,将我的 json 数据反序列化为相同的 JToken/JContainer 类型,我有点惊讶
JsonConver.Deserialize(string json) 到 JToken/JContainer
平均内存使用量:22.0 MB
平均解析时间:223 毫秒
所以,就我个人而言,Parse() 方法为JToken/JContainer 生成的对象分配的内存比使用JsonConver.Deserialize<T>() 方法时要多,这有点令人惊讶。真是出乎意料。
这部分的最后一组测试是dynamic类型使用相同的JsonConver.Deserialize<T>(string json)方法:
JsonConver.Deserialize(string json) 转为动态
平均内存使用:22.1 MB
平均解析时间:224 毫秒
老实说,我期待一些不同的结果,但似乎 JToken 只是 dynamic 的包装,这就是为什么他们使用相同的内存量并花费相同的解析时间。
所有事情都可以是好的和足够的,但总是有一些“但是”的条件。我用于测试的 json 数据很小(当然,我们总是尝试通过网络发送尽可能少的数据)。我必须使用的真实对象实例具有更大的大小,并且为了对我的真实数据真正满意,我运行了另一个测试集。现在,大小为 270 kB 的真实对象(与第一组的 4.54 kB 相比)。结果真的让我很震惊。 JToken/JContainer 的Parse() 方法失败!!!我的 8 GB RAM 机器上出现内存不足异常!!!在我附近打开任务管理器后,我看到我的测试程序的内存超过 2 GB !!!我以为这就是我的测试的结束,但我是个雄心勃勃的人,所以我继续。使用JsonConver.Deserialize<T>() 运行测试让我在这方面取得了更大的成功:
270kBs JsonConver.Deserialize()
平均内存使用:1.63 GB
平均解析时间:20 秒
是的,确实如此:将 1000 个对象解析为 JToken/JContainer 类型需要 1.63 GB 和 20 秒。使用dynamic 给了我相同的结果,所以我不会再次复制它们
如果我没有尝试使用对象解析测试我的 json,这些测试将不完整。所以我创建了一个类来描述我的 json 结构并使用JsonConver.Deserialize<T>() 方法:
JsonConver.Deserialize() 解析为 POCO 对象
平均内存使用:72 MB
平均解析时间:7.5。 s
1000 个 POCO 对象为 72 MB,而动态数据为 1.63 Gbs。
附言。而不是结论......当然,我们总是尝试使用对象来处理代码中的数据,但有时我们必须处理动态。现在您可以看到 C# 中的对象是多么高效。此外,我建议你永远不要使用JToken.Parse(),为自己节省一点内存。而 IMO,OOP 的引入是为了真正帮助开发人员并使我们的夜梦变得美好。它的工作! :)
PPS。所有有兴趣查看我的测试解决方案的人-欢迎github :)