本文以一组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优化版本。
测试代码
2
3
4
5
6
7
8
9
10
11
12
13
14
15
更多代码我就不列举了,请自行下载下面的源码。
下载
下载测试框架及源码 (本示例源码包含在新版本的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方式带来的实际的性能提升可能会更大。