在搜索Internet时找不到任何适当的答案...
我有从服务器接收的JSON
数据。它的格式每次都可能有所不同,因此我必须使用动态对象。当前在我们的项目中,我们正在使用JToken
库中的CC_2类型,但是如果我们查看其内部结构...恐怕它有很多拳击/拆箱案例,这不好 - 我们应该尽可能少地记忆因为它是一个移动应用程序。
因此,问题是:使用c#
本身使用dynamic
类型(是的,尽管它也具有拳击/拆箱),还是它们之间没有区别?它们如何使用内存使用?有人对它们做了一些基准测试?
也许这两个都有一些很好的选择?
预先感谢
所以看来没有人做过与我的问题相关的事情,我已经做了自己的测试,现在我要分享我的结果。希望他们真的有帮助。
起初,我想说我真的很震惊和惊讶。
首先是第一件事,我的测试机配置:
- HP Probook 450 G3笔记本电脑带有Intel Core i5-6200 CPU为2.40 GHz
- 8 GB的RAM
- 256MB的SSD爱国者Ignite M2,最高560MB/s read&320MB/s写IO
- Seagate SATA HDD的1000 GB
- Windows 10 Pro X64 OS
测试非常简单:有一个JSON字符串,其大小存储在文件4.54 kb中。我运行100个测试,每个测试都会创建1000个指定类型的对象(Dynamic/Jtoken/Jcontainer)。在每个测试中,我计算分配了这1000个对象的实际内存量,以及将JSON弦乐解析为指定对象类型所需的时间。所有测试完成后,我计算使用的平均内存量和每个测试集的平均时间。基于公式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
AVG。内存用法:25.7 MB
AVG。解析时间:223 ms
非常简单。现在,我通过JsonConver.Deserialize<T>(string json)
方法进行了测试,将我的JSON数据置于同一JToken/JContainer
类型中,我感到惊讶的是一点
jsonconver.deserialize(字符串json)to jtoken/jcontainer
AVG内存用法:22.0 MB
AVG。解析时间:223 ms
因此,对我个人而言,JToken/JContainer
的Parse()
方法产生的对象比使用JsonConver.Deserialize<T>()
方法分配更多的内存,这一点毫不奇怪。真的很意外。
使用相同的JsonConver.Deserialize<T>(string json)
方法,该部分的最后一组测试是使用dynamic
类型:
JSONCONVER.DESERIALIZE(String json)to dynamic
AVG。内存用法:22.1 MB
AVG解析时间:224 MS
说实话,我期待一些不同的结果,但是JToken
似乎只是围绕dynamic
的包装器,这就是为什么他们使用相同的记忆量并需要相同的解析时间。
所有事物都可能是好的,但是总会有一些"但"条件。我用于测试的JSON数据很小(当然,我们总是试图通过网络发送尽可能少的数据)。我必须使用的真实对象实例具有更大的大小,并且对我的真实数据感到非常满意,我还运行了另一个测试集。现在,大小为270 kb的真实对象(相比之下,第一组为4.54 kb)。结果真的让我震惊。JToken/JContainer
的Parse()
方法失败了!!!我在8 GB RAM机器上退出了记忆例外!!!让我靠近打开任务经理,我看到了测试程序的内存如何超过2 GB !!!我以为那是我的测试的终点,但我雄心勃勃,所以我继续。使用JsonConver.Deserialize<T>()
进行测试给我带来了更大的成功:
270KBS JSONCONVER.DESERIALIZE()
AVG。内存使用率:1.63 GB
AVG解析时间:20 S
是的,它的真实:1.63 GB和20秒,将1000个对象分析为JToken/JContainer
类型。使用Newtonsoft.JSON
0给了我相同的结果,所以我不会再复制它们
如果我没有尝试通过对象解析测试我的JSON,这些测试将不完整。因此,我创建了一个描述我的JSON结构并使用JsonConver.Deserialize<T>()
方法的类:
jsonconver.deserialize()解析到POCO对象
AVG。内存用法:72 MB
AVG。解析时间:7.5。S
72 MB,用于1000个POCO对象,与1.63GB的动态数据相比。
ps。当然,我们总是尝试使用对象来处理代码上的数据,但有时我们必须处理动态。现在,您可以看到C#中的有效对象。此外,我建议您永远不要使用JToken.Parse()
,为自己节省一些内存。IMO介绍了OOP,以真正帮助开发人员并使我们的夜间梦想变得更好。它的工作!:)
pps。所有有兴趣查看我的测试解决方案的人 - 欢迎在GitHub上:)