65.9K
CodeProject 正在变化。 阅读更多。
Home

寻找终极 DataTable 序列化器

starIconstarIconstarIconstarIconstarIcon

5.00/5 (17投票s)

2016年9月27日

CPOL

9分钟阅读

viewsIcon

35583

downloadIcon

1108

我知道“从 WebService 返回 DataSets 是魔鬼的产物”,但是……

引言

我最近遇到一个复杂且性能不佳的 ASP.NET Web Forms 应用程序,该应用程序从 WCF 服务接收大量 DataTable 对象,并且其 UI 对这些对象的字段进行大量直接绑定。

我知道 这种方法可能不是最好的,但由于 UI 的复杂性和业务逻辑直接引用了大量的 DataTable 字段,因此重写这部分将是成本过高且风险巨大。

因此,我开始寻找终极的 DataTable 序列化器。

已测试的序列化器

以下是我测试过的序列化器列表。

在人工生成的 DataTable 对象以及从 AdventureWorks2012 SQL Server 示例数据库的 Production 架构中检索到的 DataTable 对象语料库上,对每个序列化器的一致性和性能都进行了多次验证和测量。

所有测试均在配备 Windows 10 Pro x64、Intel Core i3 540 @ 3.06 Ghz CPU 和 8 GB DDR3 RAM @ 1333 Mhz 的计算机上进行。

DataTable WriteXml/ReadXml 方法

此序列化器使用 DataTable 类的 WriteXmlReadXml 方法,这些方法允许将 DataTable 对象当前的内容和架构写入 XML 并读回。

二进制格式化器

此序列化器使用位于 System.Runtime.Serialization.Formatters.Binary 命名空间中的 BinaryFormatter 类,该类提供了一种以二进制格式序列化和反序列化对象或连接对象整个图的通用方法。

对于使用 BinaryFormatter 类对 DataTable 对象进行序列化,已将 DataTable 对象的 RemotingFormat 属性设置为 RemotingFormat.Binary

压缩二进制格式化器

此序列化器仅在上述相同二进制格式化器输出的基础上添加了一个压缩层。

Protocol Buffers

Protocol Buffers 是 Google 的语言无关、平台无关、可扩展的结构化数据序列化机制——可以将其想象成 XML,但更小、更快、更简单。

此序列化器使用了 Marc Gravell 的 protobuf-net 实现,以及 Richard Dingwall 的 protobuf-net-data 针对 DataTable 对象在其之上的特定扩展。

压缩 Protocol Buffers

此序列化器仅在上述相同 Protocol Buffers 序列化器输出的基础上添加了一个压缩层。

快速序列化器

此序列化器由 SimmoTech 开发,旨在通过对拥有数据(作者的话,即相对安全可序列化的对象数据)做出一些假设来提高对象序列化的性能。

您可以在 这里这里 找到作者关于“优化 .NET 中的序列化”的两部分文章。

轻量级序列化器

此序列化器由 Shital Shah 开发,它使用 BinaryFormatter 类序列化二维对象数组而不是 DataTable 对象,从而节省了少量字节,但代价是需要填充该数组对象,并且需要单独调用 DataTable 类的 WriteXmlSchema 方法来导出 DataTable 对象的架构以及数据。

您可以在 这里 找到作者关于“轻量级 DataTable 序列化”的文章。

Drew DataSet 格式化器

此序列化器由 Drew Noakes 开发,它使用与上面描述的轻量级序列化器类似的方法,使用 BinaryFormatter 类序列化从 DataTable 对象填充的自定义 Table 对象,并且与上述方法一样,节省了少量字节,但代价是需要填充该自定义 Table 对象。

您可以在 这里 找到作者关于“DataSet 序列化”的文章。

DataTable 自定义格式化器

此序列化器由我本人编写,专门用于 DataTable 对象,因此它只序列化最少的数据和元数据,避免了更通用(也更强大)的序列化器中昂贵的例程。默认情况下,在序列化器的输出中会添加一个压缩层。

序列化器原始测试结果

Synthetic.Type1Large (36 列 x 10,000 行 = 360,000 个单元格)

描述   大小 (字节)   序列化 (毫秒)   反序列化 (毫秒)
DataTable WriteXml/ReadXml 方法 13,435,801 411.941 ± 4.932 467.279 ± 3.059
二进制格式化器 2,660,024 217.003 ± 1.254 317.036 ± 6.738
压缩二进制格式化器 821,369 232.951 ± 1.044 323.181 ± 2.818
Protocol Buffers (1) 失败 失败 失败
Compressed Protocol Buffers (2) 失败 失败 失败
快速序列化器 1,696,752 74.906 ± 0.782 106.662 ± 0.925
轻量级序列化器 3,324,311 339.926 ± 8.636 700.616 ± 8.806
Drew DataSet 格式化器 3,182,058 376.337 ± 1.704 668.623 ± 10.188
DataTable 自定义格式化器 535,194 60.743 ± 0.264 127.290 ± 0.929
未压缩 DataTable 自定义格式化器 2,966,841 49.940 ± 0.293 115.219 ± 0.635

(1) ProtoBuf.Data.UnsupportedColumnTypeException: 无法序列化类型为 'System.SByte' 的数据列。仅支持以下列类型:Boolean、Byte、Byte[]、Char、Char[]、DateTime、Decimal、Double、Guid、Int16、Int32、Int64、Single、String、TimeSpan。
(2) ProtoBuf.Data.UnsupportedColumnTypeException: 无法序列化类型为 'System.SByte' 的数据列。仅支持以下列类型:Boolean、Byte、Byte[]、Char、Char[]、DateTime、Decimal、Double、Guid、Int16、Int32、Int64、Single、String、TimeSpan。

Synthetic.Type2Small (4 列 x 10 行 = 40 个单元格)

描述   大小 (字节)   序列化 (毫秒)   反序列化 (毫秒)
DataTable WriteXml/ReadXml 方法 3,707 0.116 ± 0.000 0.286 ± 0.001
二进制格式化器 7,609 0.272 ± 0.000 0.361 ± 0.000
压缩二进制格式化器 3,549 0.367 ± 0.021 0.414 ± 0.010
Protocol Buffers 1,354 0.068 ± 0.000 0.145 ± 0.001
压缩 Protocol Buffers 1,363 0.086 ± 0.000 0.148 ± 0.000
快速序列化器 1,420 0.017 ± 0.000 0.036 ± 0.000
轻量级序列化器 2,559 0.127 ± 0.000 0.274 ± 0.002
Drew DataSet 格式化器 2,192 0.060 ± 0.000 0.132 ± 0.000
DataTable 自定义格式化器 1,436 0.025 ± 0.000 0.050 ± 0.000
未压缩 DataTable 自定义格式化器 1,427 0.010 ± 0.000 0.045 ± 0.000


Synthetic.Type2Large (4 列 x 50,000 行 = 200,000 个单元格)

描述   大小 (字节)   序列化 (毫秒)   反序列化 (毫秒)
DataTable WriteXml/ReadXml 方法 13,889,857 203.162 ± 2.186 390.192 ± 3.717
二进制格式化器 7,149,929 163.989 ± 0.442 315.307 ± 7.828
压缩二进制格式化器 6,534,987 249.564 ± 0.573 393.697 ± 8.944
Protocol Buffers 6,583,542 74.065 ± 0.467 293.169 ± 11.353
压缩 Protocol Buffers 6,047,817 151.984 ± 0.342 364.331 ± 12.658
快速序列化器 6,867,204 159.638 ± 1.432 214.509 ± 2.906
轻量级序列化器 7,900,979 282.263 ± 3.277 1002.640 ± 13.129
Drew DataSet 格式化器 7,200,752 201.556 ± 0.494 392.789 ± 5.377
DataTable 自定义格式化器 6,045,369 134.320 ± 0.826 284.072 ± 6.848
未压缩 DataTable 自定义格式化器 6,550,117 54.208 ± 0.174 222.759 ± 4.164


Production.Product (25 列 x 504 行 = 12,600 个单元格)

描述   大小 (字节)   序列化 (毫秒)   反序列化 (毫秒)
DataTable WriteXml/ReadXml 方法 415,908 9.178 ± 0.060 12.013 ± 0.011
二进制格式化器 114,997 7.518 ± 0.030 7.172 ± 0.006
压缩二进制格式化器 40,642 8.283 ± 0.025 7.896 ± 0.032
Protocol Buffers (1) 失败 失败 失败
Compressed Protocol Buffers (2) 失败 失败 失败
Fast Serializer (3) 失败 失败 失败
轻量级序列化器 115,718 8.829 ± 0.066 10.159 ± 0.020
Drew DataSet 格式化器 107,232 9.262 ± 0.043 13.954 ± 0.117
DataTable 自定义格式化器 25,885 1.674 ± 0.008 2.611 ± 0.003
未压缩 DataTable 自定义格式化器 79,342 1.207 ± 0.006 2.197 ± 0.002

(1) System.Exception: 反序列化数据表的 XML 表示与原始数据表不匹配。
(2) System.Exception: 反序列化数据表的 XML 表示与原始数据表不匹配。
(3) System.Exception: 反序列化数据表的 XML 表示与原始数据表不匹配。

Production.ProductDescription (4 列 x 762 行 = 3,048 个单元格)

描述   大小 (字节)   序列化 (毫秒)   反序列化 (毫秒)
DataTable WriteXml/ReadXml 方法 305,996 5.729 ± 0.026 6.786 ± 0.004
二进制格式化器 135,756 6.310 ± 0.032 6.476 ± 0.006
压缩二进制格式化器 75,183 7.370 ± 0.006 7.447 ± 0.033
Protocol Buffers 117,871 1.375 ± 0.003 2.515 ± 0.003
压缩 Protocol Buffers 67,689 2.415 ± 0.012 3.475 ± 0.013
快速序列化器 112,598 1.480 ± 0.000 1.683 ± 0.001
轻量级序列化器 143,633 7.105 ± 0.024 7.675 ± 0.005
Drew DataSet 格式化器 132,694 6.172 ± 0.022 6.823 ± 0.005
DataTable 自定义格式化器 67,156 2.100 ± 0.008 2.668 ± 0.014
未压缩 DataTable 自定义格式化器 117,440 1.060 ± 0.004 1.718 ± 0.002


Production.ProductPhoto (6 列 x 101 行 = 606 个单元格)

描述   大小 (字节)   序列化 (毫秒)   反序列化 (毫秒)
DataTable WriteXml/ReadXml 方法 2,715,494 21.841 ± 0.149 38.668 ± 0.258
二进制格式化器 2,025,340 6.428 ± 0.067 2.203 ± 0.015
压缩二进制格式化器 2,025,349 22.867 ± 0.093 6.929 ± 0.027
Protocol Buffers 2,013,896 7.420 ± 0.017 1.796 ± 0.007
压缩 Protocol Buffers 2,013,905 22.922 ± 0.064 5.973 ± 0.039
快速序列化器 2,013,926 7.370 ± 0.022 1.283 ± 0.001
轻量级序列化器 2,019,925 6.862 ± 0.015 2.119 ± 0.001
Drew DataSet 格式化器 2,018,227 6.393 ± 0.016 1.908 ± 0.001
DataTable 自定义格式化器 2,014,505 22.852 ± 0.046 5.973 ± 0.025
未压缩 DataTable 自定义格式化器 2,014,496 7.240 ± 0.020 1.335 ± 0.018


Production.ProductReview (8 列 x 4 行 = 32 个单元格)

描述   大小 (字节)   序列化 (毫秒)   反序列化 (毫秒)
DataTable WriteXml/ReadXml 方法 7,839 0.150 ± 0.000 0.379 ± 0.002
二进制格式化器 15,450 0.437 ± 0.000 0.546 ± 0.000
压缩二进制格式化器 6,406 0.544 ± 0.001 0.640 ± 0.003
Protocol Buffers 5,284 0.089 ± 0.000 0.203 ± 0.000
压缩 Protocol Buffers 3,799 0.148 ± 0.000 0.256 ± 0.001
快速序列化器 5,339 0.039 ± 0.000 0.074 ± 0.000
轻量级序列化器 6,639 0.149 ± 0.000 0.341 ± 0.002
Drew DataSet 格式化器 6,161 0.077 ± 0.000 0.170 ± 0.000
DataTable 自定义格式化器 3,842 0.081 ± 0.000 0.134 ± 0.000
未压缩 DataTable 自定义格式化器 5,437 0.024 ± 0.000 0.082 ± 0.000
© . All rights reserved.