本文以一组Entity vs Dataset的性能测试数据为基础,比较以Entity作为DTO和Dataset作为DTO的性能差异。测试可能不一定严密,但是一定程度上能够比较出优劣。希望能为您选择 .Net下不同的数据承载方式、序列化方式、DTO的选择,多一点参考。在本测试中,每个执行过程,对于Entity,我们将先用DataReader读出数据,使用索引将数据填充到Entity,序列化,再反序列化;对于Dataset,将先读取所有数据到Dataset,序列化,再反序列化,最后通过索引填充Dataset中的数据到Entity。也就是说,无论对Entity还是Dataset,我们都尽可能的取其最佳性能的执行方式,从而将性能瓶颈留在了序列化和反序列化方式上。您可以注意到,Dataset的序列化和反序列化性能是非常突出的,但是,我们基于Entity的自定义序列化方式的综合性能,超越了Dataset。
04/18补充:新增.NET JSON序列化对照。关于JSON的更多介绍请参见:http://www.json.org/。不过值得一提的是,官方提供的.Net实现写得那个烂得简直没话说。本测试使用Teddy修改由化后的.Net版本,性能是官方版本的30-40倍。
测试报告
就让我们先从一个测试报告开始,该测试读取Northwind数据库中Order Details Extended视图的所有数据,RepeatTime表示每个步骤(读数据、序列化、反序列化等等着每个步骤)被重复的次数。表中的时间数值单位为毫秒。
Ilungasoft Framework Data Access & Entities Serialization Performance Test
Title | Read Data Time | Serialize Time | Serialized Xml Size | DeserializeTime | Total Run Time |
---|---|---|---|---|---|
Entities Xml Serialize | 844 | 1766 | 702783 | 1750 | 4360 |
Entities Soap Serialize | 328 | 4094 | 3031007 | 6203 | 10625 |
Entities Custom Serialize | 359 | 594 | 598565 | 625 | 1578 |
DataSet Serialize | 515 | 532 | 586200 | 2047 | 3094 |
Entities JSON Serialize | 484 | 625 | 325298 | 641 | 1750 |
Title | Read Data Time | Serialize Time | Serialized Xml Size | Deserialize Time | Total Run Time |
---|---|---|---|---|---|
Entities Xml Serialize | 1093 | 2594 | 702783 | 3797 | 7484 |
Entities Soap Serialize | 734 | 8032 | 3031007 | 12000 | 20766 |
Entities Custom Serialize | 671 | 1188 | 598565 | 1234 | 3093 |
DataSet Serialize | 657 | 1062 | 586200 | 6563 | 8282 |
Entities JSON Serialize | 781 | 1094 | 325298 | 1093 | 2968 |
Title | Read Data Time | Serialize Time | Serialized Xml Size | Deserialize Time | Total Run Time |
---|---|---|---|---|---|
Entities Xml Serialize | 938 | 4140 | 702783 | 5547 | 10625 |
Entities Soap Serialize | 1094 | 12578 | 3031007 | 18891 | 32563 |
Entities Custom Serialize | 1140 | 1922 | 598565 | 2188 | 5250 |
DataSet Serialize | 1156 | 1438 | 586200 | 14984 | 17578 |
Entities JSON Serialize | 1141 | 1656 | 325298 | 1703 | 4500 |
Title | Read Data Time | Serialize Time | Serialized Xml Size | Deserialize Time | Total Run Time |
---|---|---|---|---|---|
Entities Xml Serialize | 1594 | 5047 | 702783 | 6968 | 13609 |
Entities Soap Serialize | 1391 | 16844 | 3031007 | 26093 | 44328 |
Entities Custom Serialize | 1875 | 2469 | 598565 | 2735 | 7079 |
DataSet Serialize | 1828 | 2093 | 586200 | 25969 | 29890 |
Entities JSON Serialize | 1719 | 2437 | 325298 | 2500 | 6656 |
解析
以上的测试中,除了Dataset Serialize是使用Dataset作为DTO来序列化和反序列化数据之外,其他的都是使用Entity方式来处理。Xml Serialize表示系统默认的XmlSerializer序列化方式,SoapSerilialize自然是系统默认的SoapFormatter序列化,CustomSerialize则是自定义的序列化方式(目前采用的是自定义序列化+XmlSerializer反序列化结合的方式)。Json Serialization为Teddy的Json优化版本。
测试代码
![](/Images/OutliningIndicators/None.gif)
2
![](/Images/OutliningIndicators/None.gif)
3
![](/Images/OutliningIndicators/None.gif)
4
![](/Images/OutliningIndicators/None.gif)
5
![](/Images/OutliningIndicators/None.gif)
6
![](/Images/OutliningIndicators/None.gif)
7
![](/Images/OutliningIndicators/None.gif)
8
![](/Images/OutliningIndicators/None.gif)
9
![](/Images/OutliningIndicators/None.gif)
10
![](/Images/OutliningIndicators/None.gif)
11
![](/Images/OutliningIndicators/None.gif)
12
![](/Images/OutliningIndicators/None.gif)
13
![](/Images/OutliningIndicators/None.gif)
14
![](/Images/OutliningIndicators/None.gif)
15
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
16
![](/Images/OutliningIndicators/InBlock.gif)
17
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
18
![](/Images/OutliningIndicators/InBlock.gif)
19
![](/Images/OutliningIndicators/InBlock.gif)
20
![](/Images/OutliningIndicators/InBlock.gif)
21
![](/Images/OutliningIndicators/InBlock.gif)
22
![](/Images/OutliningIndicators/InBlock.gif)
23
![](/Images/OutliningIndicators/InBlock.gif)
24
![](/Images/OutliningIndicators/InBlock.gif)
25
![](/Images/OutliningIndicators/InBlock.gif)
26
![](/Images/OutliningIndicators/InBlock.gif)
27
![](/Images/OutliningIndicators/InBlock.gif)
28
![](/Images/OutliningIndicators/InBlock.gif)
29
![](/Images/OutliningIndicators/InBlock.gif)
30
![](/Images/OutliningIndicators/InBlock.gif)
31
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
32
![](/Images/OutliningIndicators/InBlock.gif)
33
![](/Images/OutliningIndicators/InBlock.gif)
34
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
35
![](/Images/OutliningIndicators/InBlock.gif)
36
![](/Images/OutliningIndicators/InBlock.gif)
37
![](/Images/OutliningIndicators/InBlock.gif)
38
![](/Images/OutliningIndicators/InBlock.gif)
39
![](/Images/OutliningIndicators/InBlock.gif)
40
![](/Images/OutliningIndicators/InBlock.gif)
41
![](/Images/OutliningIndicators/InBlock.gif)
42
![](/Images/OutliningIndicators/InBlock.gif)
43
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
44
![](/Images/OutliningIndicators/InBlock.gif)
45
![](/Images/OutliningIndicators/InBlock.gif)
46
![](/Images/OutliningIndicators/InBlock.gif)
47
![](/Images/OutliningIndicators/InBlock.gif)
48
![](/Images/OutliningIndicators/InBlock.gif)
49
![](/Images/OutliningIndicators/InBlock.gif)
50
![](/Images/OutliningIndicators/InBlock.gif)
51
![](/Images/OutliningIndicators/InBlock.gif)
52
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
53
![](/Images/OutliningIndicators/InBlock.gif)
54
![](/Images/OutliningIndicators/InBlock.gif)
55
![](/Images/OutliningIndicators/InBlock.gif)
56
![](/Images/OutliningIndicators/InBlock.gif)
57
![](/Images/OutliningIndicators/InBlock.gif)
58
![](/Images/OutliningIndicators/InBlock.gif)
59
![](/Images/OutliningIndicators/InBlock.gif)
60
![](/Images/OutliningIndicators/InBlock.gif)
61
![](/Images/OutliningIndicators/InBlock.gif)
62
![](/Images/OutliningIndicators/InBlock.gif)
63
![](/Images/OutliningIndicators/InBlock.gif)
64
![](/Images/OutliningIndicators/InBlock.gif)
65
![](/Images/OutliningIndicators/InBlock.gif)
66
![](/Images/OutliningIndicators/InBlock.gif)
67
![](/Images/OutliningIndicators/InBlock.gif)
68
![](/Images/OutliningIndicators/InBlock.gif)
69
![](/Images/OutliningIndicators/InBlock.gif)
70
![](/Images/OutliningIndicators/InBlock.gif)
71
![](/Images/OutliningIndicators/InBlock.gif)
72
![](/Images/OutliningIndicators/InBlock.gif)
73
![](/Images/OutliningIndicators/InBlock.gif)
74
![](/Images/OutliningIndicators/InBlock.gif)
75
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
76
![](/Images/OutliningIndicators/InBlock.gif)
77
![](/Images/OutliningIndicators/InBlock.gif)
78
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
79
![](/Images/OutliningIndicators/InBlock.gif)
80
![](/Images/OutliningIndicators/InBlock.gif)
81
![](/Images/OutliningIndicators/InBlock.gif)
82
![](/Images/OutliningIndicators/InBlock.gif)
83
![](/Images/OutliningIndicators/InBlock.gif)
84
![](/Images/OutliningIndicators/InBlock.gif)
85
![](/Images/OutliningIndicators/InBlock.gif)
86
![](/Images/OutliningIndicators/InBlock.gif)
87
![](/Images/OutliningIndicators/InBlock.gif)
88
![](/Images/OutliningIndicators/InBlock.gif)
89
![](/Images/OutliningIndicators/InBlock.gif)
90
![](/Images/OutliningIndicators/InBlock.gif)
91
![](/Images/OutliningIndicators/InBlock.gif)
92
![](/Images/OutliningIndicators/InBlock.gif)
93
![](/Images/OutliningIndicators/InBlock.gif)
94
![](/Images/OutliningIndicators/InBlock.gif)
95
![](/Images/OutliningIndicators/InBlock.gif)
96
![](/Images/OutliningIndicators/InBlock.gif)
97
![](/Images/OutliningIndicators/InBlock.gif)
98
![](/Images/OutliningIndicators/InBlock.gif)
99
![](/Images/OutliningIndicators/InBlock.gif)
100
![](/Images/OutliningIndicators/InBlock.gif)
101
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
102
![](/Images/OutliningIndicators/InBlock.gif)
103
![](/Images/OutliningIndicators/InBlock.gif)
104
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
105
![](/Images/OutliningIndicators/InBlock.gif)
106
![](/Images/OutliningIndicators/InBlock.gif)
107
![](/Images/OutliningIndicators/InBlock.gif)
108
![](/Images/OutliningIndicators/InBlock.gif)
109
![](/Images/OutliningIndicators/InBlock.gif)
110
![](/Images/OutliningIndicators/InBlock.gif)
111
![](/Images/OutliningIndicators/InBlock.gif)
112
![](/Images/OutliningIndicators/InBlock.gif)
113
![](/Images/OutliningIndicators/InBlock.gif)
114
![](/Images/OutliningIndicators/InBlock.gif)
115
![](/Images/OutliningIndicators/InBlock.gif)
116
![](/Images/OutliningIndicators/InBlock.gif)
117
![](/Images/OutliningIndicators/InBlock.gif)
118
![](/Images/OutliningIndicators/InBlock.gif)
119
![](/Images/OutliningIndicators/InBlock.gif)
120
![](/Images/OutliningIndicators/InBlock.gif)
121
![](/Images/OutliningIndicators/InBlock.gif)
122
![](/Images/OutliningIndicators/InBlock.gif)
123
![](/Images/OutliningIndicators/InBlock.gif)
124
![](/Images/OutliningIndicators/InBlock.gif)
125
![](/Images/OutliningIndicators/InBlock.gif)
126
![](/Images/OutliningIndicators/InBlock.gif)
127
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
128
![](/Images/OutliningIndicators/InBlock.gif)
129
![](/Images/OutliningIndicators/InBlock.gif)
130
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
131
![](/Images/OutliningIndicators/InBlock.gif)
132
![](/Images/OutliningIndicators/InBlock.gif)
133
![](/Images/OutliningIndicators/InBlock.gif)
134
![](/Images/OutliningIndicators/InBlock.gif)
135
![](/Images/OutliningIndicators/InBlock.gif)
136
![](/Images/OutliningIndicators/InBlock.gif)
137
![](/Images/OutliningIndicators/InBlock.gif)
138
![](/Images/OutliningIndicators/InBlock.gif)
139
![](/Images/OutliningIndicators/InBlock.gif)
140
![](/Images/OutliningIndicators/InBlock.gif)
141
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
142
![](/Images/OutliningIndicators/InBlock.gif)
143
![](/Images/OutliningIndicators/InBlock.gif)
144
![](/Images/OutliningIndicators/InBlock.gif)
145
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
146
![](/Images/OutliningIndicators/InBlock.gif)
147
![](/Images/OutliningIndicators/InBlock.gif)
148
![](/Images/OutliningIndicators/InBlock.gif)
149
![](/Images/OutliningIndicators/InBlock.gif)
150
![](/Images/OutliningIndicators/InBlock.gif)
151
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
152
![](/Images/OutliningIndicators/InBlock.gif)
153
![](/Images/OutliningIndicators/InBlock.gif)
154
![](/Images/OutliningIndicators/InBlock.gif)
155
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
156
![](/Images/OutliningIndicators/InBlock.gif)
157
![](/Images/OutliningIndicators/InBlock.gif)
158
![](/Images/OutliningIndicators/InBlock.gif)
159
![](/Images/OutliningIndicators/InBlock.gif)
160
![](/Images/OutliningIndicators/InBlock.gif)
161
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
162
![](/Images/OutliningIndicators/InBlock.gif)
163
![](/Images/OutliningIndicators/InBlock.gif)
164
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
165
![](/Images/OutliningIndicators/InBlock.gif)
166
![](/Images/OutliningIndicators/InBlock.gif)
167
![](/Images/OutliningIndicators/InBlock.gif)
168
![](/Images/OutliningIndicators/InBlock.gif)
169
![](/Images/OutliningIndicators/InBlock.gif)
170
![](/Images/OutliningIndicators/InBlock.gif)
171
![](/Images/OutliningIndicators/InBlock.gif)
172
![](/Images/OutliningIndicators/InBlock.gif)
173
![](/Images/OutliningIndicators/InBlock.gif)
174
![](/Images/OutliningIndicators/InBlock.gif)
175
![](/Images/OutliningIndicators/InBlock.gif)
176
![](/Images/OutliningIndicators/InBlock.gif)
177
![](/Images/OutliningIndicators/InBlock.gif)
178
![](/Images/OutliningIndicators/InBlock.gif)
179
![](/Images/OutliningIndicators/InBlock.gif)
180
![](/Images/OutliningIndicators/InBlock.gif)
181
![](/Images/OutliningIndicators/InBlock.gif)
182
![](/Images/OutliningIndicators/InBlock.gif)
183
![](/Images/OutliningIndicators/InBlock.gif)
184
![](/Images/OutliningIndicators/InBlock.gif)
185
![](/Images/OutliningIndicators/InBlock.gif)
186
![](/Images/OutliningIndicators/InBlock.gif)
187
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
188
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
更多代码我就不列举了,请自行下载下面的源码。
下载
下载测试框架及源码 (本示例源码包含在新版本的Ilungasoft Framework v1.4.4的目录中的dist\Sample5)
小结
本测试示例的目的并不是要终结Dataset作为DTO,尽管Entity作为DTO的性能是可以超越Dataset的,但Teddy觉得,Dataset的性能确实是相当好的,作为一个通用的DTO还是非常适合的(尤其是可以和异构的其他.Net系统方便共享和传递数据)。
补遗:
后续的测试中还发现,无论是XmlSerializer的序列化方式都不够稳定,特别是反序列化时,尤其是对符合类型和数组的序列化。因此,对于大多数基于.Net的程序构架,Teddy还是推荐使用Dataset作为DTO,除非对性能要求非常高时在使用自定义的序列化方式。
4/19:
更新了CustomSerizlize算法,使得其执行时间仅为Dataset的1/2 - 1/10。数据量越大,自定义序列化的优势就越明显。
新增的JSON序列化性能基本和自定义Xml 序列化相当,当数据量较大时,要比自定义Xml序列化方式稍好一点点。
但是,请注意,JSON的序列化后的文本大小只有Dataset的一半,对于需要远程通信的程序来讲,JSON方式将极大的减少需要通信的数据量,因此,JSON方式带来的实际的性能提升可能会更大。