解析动态JSON数据时最好使用什么:动态类型内置的JToken或c#

And*_*rew 2 c# json dynamic json.net

搜索互联网时找不到正确的答案...

JSON收到了来自服务器的数据。每次的格式都可能不同,因此我必须使用动态对象。当前在我们的项目中,我们正在使用库中的JToken类型Newtonsoft.JSON,但是如果我们看一下它的内部结构,恐怕它有很多装箱/拆箱的情况,这是不好的-我们应该使用尽可能少的内存,因为移动应用程序。

因此,问题是:使用dynamic类型c#本身更好(是的,尽管它也具有装箱/拆箱功能)还是它们之间没有区别?它们如何利用内存使用?有人对它们进行过基准测试吗?

也许对于他们两个都有一些好的选择?

提前致谢

And*_*rew 7

因此,似乎没有人做与我的问题有关的事情,并且我做了自己的测试,现在我不愿分享自己的结果。希望他们会有所帮助。

首先,我想说我对某些结果感到非常震惊和惊讶。

首先是我的测试机配置:

  • 带有2.40 GHz Intel Core i5-6200 CPU的HP Probook 450 G3笔记本电脑
  • 8 GB的RAM
  • 256MB SSD Patriot Ignite M2,最高560MB / s读取和320MB / s写入IO
  • 希捷SATA硬盘1000 GB
  • 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毫秒

很简单 现在我运行了testsusing 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(字符串json)动态

平均 记忆体使用量:22.1 MB

平均解析时间:224毫秒

老实说,我期望得到一些不同的结果,但是似乎这JToken只是一个包装,dynamic这就是为什么他们使用相同的内存量并花费相同的解析时间。

万事俱备,但总会有一些“条件”。我用于测试的json数据的大小很小(当然,我们总是尝试通过网络发送尽可能少的数据)。我必须使用的真实对象实例具有更大的大小,为了对真实数据真正满意,我运行了另一个测试集。现在,大小为270 kB的真实对象(在第一组中为4.54 kB)。结果真的让我震惊。JToken/JContainerParse()方法失败了!!!我的8 GB RAM计算机上出现内存不足异常!!!在我附近打开任务管理器后,我看到测试程序的内存超过2 GB !!!我以为那是测试的终点,但我是个有野心的家伙,所以我继续。运行测试JsonConver.Deserialize<T>()为我带来了更多成功:

270kB JsonConver.Deserialize()

平均 记忆体使用量:1.63 GB

平均解析时间:20秒

是的,它是正确的:1.63 GB和20秒的时间将1000个对象解析为JToken/JContainer类型。与the一起工作dynamic给了我相同的结果,所以我不再复制它们

如果我没有尝试使用对象解析来测试json,则这些测试将不完整。所以我创建了一个描述我的json结构和使用JsonConver.Deserialize<T>()方法的类:

JsonConver.Deserialize()解析为POCO对象

平均 记忆体使用量:72 MB

平均 解析时间:7.5。s

1000个POCO对象为72 MB,而动态数据为1.63Gb。

PS。而不是得出结论……当然,我们总是尝试使用对象来处理代码中的数据,但是有时我们必须处理动态问题。现在您可以看到C#中对象的效率如何。而且,我建议您不要使用JToken.Parse(),为自己节省一些内存。引入IMO,OOP可以真正帮助开发人员并使我们的夜晚梦想成真。它的工作!:)

PPS。所有有兴趣看到我的测试解决方案的人-欢迎访问github :)