.Net 2.0: Entity as DTO vs Dataset as DTO / Xml Serialization vs JSON Serialization

49 篇文章 0 订阅
35 篇文章 0 订阅

本文以一组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


Repeat Time = 10
TitleRead Data TimeSerialize TimeSerialized Xml SizeDeserializeTimeTotal Run Time
Entities Xml Serialize844176670278317504360
Entities Soap Serialize32840943031007620310625
Entities Custom Serialize3595945985656251578
DataSet Serialize51553258620020473094
Entities JSON Serialize4846253252986411750

Repeat Time = 20
TitleRead Data TimeSerialize TimeSerialized Xml SizeDeserialize TimeTotal Run Time
Entities Xml Serialize1093259470278337977484
Entities Soap Serialize734803230310071200020766
Entities Custom Serialize671118859856512343093
DataSet Serialize657106258620065638282
Entities JSON Serialize781109432529810932968

Repeat Time = 30
TitleRead Data TimeSerialize TimeSerialized Xml SizeDeserialize TimeTotal Run Time
Entities Xml Serialize9384140702783554710625
Entities Soap Serialize10941257830310071889132563
Entities Custom Serialize1140192259856521885250
DataSet Serialize115614385862001498417578
Entities JSON Serialize1141165632529817034500

Repeat Time = 40
TitleRead Data TimeSerialize TimeSerialized Xml SizeDeserialize TimeTotal Run Time
Entities Xml Serialize15945047702783696813609
Entities Soap Serialize13911684430310072609344328
Entities Custom Serialize1875246959856527357079
DataSet Serialize182820935862002596929890
Entities JSON Serialize1719243732529825006656

解析

以上的测试中,除了Dataset Serialize是使用Dataset作为DTO来序列化和反序列化数据之外,其他的都是使用Entity方式来处理。Xml Serialize表示系统默认的XmlSerializer序列化方式,SoapSerilialize自然是系统默认的SoapFormatter序列化,CustomSerialize则是自定义的序列化方式(目前采用的是自定义序列化+XmlSerializer反序列化结合的方式)。Json Serialization为Teddy的Json优化版本。

测试代码

  1 using  System;
  2 using  System.Data;
  3 using  System.Collections;
  4 using  System.Configuration;
  5 using  System.Web;
  6 using  System.Web.Security;
  7 using  System.Web.UI;
  8 using  System.Web.UI.WebControls;
  9 using  System.Web.UI.WebControls.WebParts;
 10 using  System.Web.UI.HtmlControls;
 11 using  Ilungasoft.Framework.Common;
 12 using  Ilungasoft.Framework.Data.Facade;
 13
 14 public  partial  class  _Default : System.Web.UI.Page 
 15 {
 16    protected void Page_Load(object sender, EventArgs e)
 17    {
 18        repeatTime = 10;
 19        reportView1.DataSource = DoTest();
 20
 21        repeatTime = 20;
 22        reportView2.DataSource = DoTest();
 23
 24        repeatTime = 30;
 25        reportView3.DataSource = DoTest();
 26
 27        repeatTime = 40;
 28        reportView4.DataSource = DoTest();
 29
 30        DataBind();
 31    }

 32
 33    private TestReport[] DoTest()
 34    {
 35        TestReport[] testReports = new TestReport[5];
 36        testReports[0= DoTest1();
 37        testReports[1= DoTest2();
 38        testReports[2= DoTest3();
 39        testReports[3= DoTest4();
 40        testReports[4= DoTest5();
 41
 42        return testReports;
 43    }

 44
 45    private long time;
 46    private DataSet ds;
 47    private Order_nbsp_Details_nbsp_Extended[] orderDetails;
 48    public string xml;
 49    private int repeatTime = 10;
 50
 51    private TestReport DoTest1()
 52    {
 53        TestReport testReport = new TestReport();
 54        testReport.Title = "Entities Xml Serialize";
 55
 56        time = System.Environment.TickCount;
 57        for (int i = 0; i < repeatTime; i++)
 58            orderDetails = DefaultGateway.SelectAll<Order_nbsp_Details_nbsp_Extended>();
 59        testReport.ReadDataTime = System.Environment.TickCount - time;
 60
 61        time = System.Environment.TickCount;
 62        for (int i = 0; i < repeatTime; i++)
 63            xml = SerializeHelper.SerializeArray(orderDetails);
 64        testReport.SerializeTime = System.Environment.TickCount - time;
 65        testReport.SerializedXmlSize = xml.Length;
 66
 67        time = System.Environment.TickCount;
 68        for (int i = 0; i < repeatTime; i++)
 69            orderDetails = SerializeHelper.Deserialize<Order_nbsp_Details_nbsp_Extended[]>(EntityFactory<Order_nbsp_Details_nbsp_Extended>.GetDynamicEntityType().MakeArrayType(), xml);
 70        testReport.DeserializeTime = System.Environment.TickCount - time;
 71
 72        testReport.TotalRunTime = testReport.ReadDataTime + testReport.SerializeTime + testReport.DeserializeTime;
 73
 74        return testReport;
 75    }

 76
 77    private TestReport DoTest2()
 78    {
 79        TestReport testReport = new TestReport();
 80        testReport.Title = "Entities Soap Serialize";
 81
 82        time = System.Environment.TickCount;
 83        for (int i = 0; i < repeatTime; i++)
 84            orderDetails = DefaultGateway.SelectAll<Order_nbsp_Details_nbsp_Extended>();
 85        testReport.ReadDataTime = System.Environment.TickCount - time;
 86
 87        time = System.Environment.TickCount;
 88        for (int i = 0; i < repeatTime; i++)
 89            xml = SerializeHelper.SoapSerialize(orderDetails);
 90        testReport.SerializeTime = System.Environment.TickCount - time;
 91        testReport.SerializedXmlSize = xml.Length;
 92
 93        time = System.Environment.TickCount;
 94        for (int i = 0; i < repeatTime; i++)
 95            orderDetails = SerializeHelper.SoapDeserialize<Order_nbsp_Details_nbsp_Extended[]>(xml);
 96        testReport.DeserializeTime = System.Environment.TickCount - time;
 97
 98        testReport.TotalRunTime = testReport.ReadDataTime + testReport.SerializeTime + testReport.DeserializeTime;
 99
100        return testReport;
101    }

102
103    private TestReport DoTest3()
104    {
105        TestReport testReport = new TestReport();
106        testReport.Title = "Entities Custom Serialize";
107
108        time = System.Environment.TickCount;
109        for (int i = 0; i < repeatTime; i++)
110            orderDetails = DefaultGateway.SelectAll<Order_nbsp_Details_nbsp_Extended>();
111        testReport.ReadDataTime = System.Environment.TickCount - time;
112
113        time = System.Environment.TickCount;
114        for (int i = 0; i < repeatTime; i++)
115            xml = SerializeHelper.SerializeEntityArray(orderDetails);
116        testReport.SerializeTime = System.Environment.TickCount - time;
117        testReport.SerializedXmlSize = xml.Length;
118
119        time = System.Environment.TickCount;
120        for (int i = 0; i < repeatTime; i++)
121            orderDetails = SerializeHelper.DeserializeEntityArray<Order_nbsp_Details_nbsp_Extended>(xml);
122        testReport.DeserializeTime = System.Environment.TickCount - time;
123
124        testReport.TotalRunTime = testReport.ReadDataTime + testReport.SerializeTime + testReport.DeserializeTime;
125
126        return testReport;
127    }

128
129    private TestReport DoTest4()
130    {
131        TestReport testReport = new TestReport();
132        testReport.Title = "DataSet Serialize";
133
134        time = System.Environment.TickCount;
135        for (int i = 0; i < repeatTime; i++)
136            ds = DefaultGateway.SelectDataSet("select * from [Order Details Extended]");
137        testReport.ReadDataTime = System.Environment.TickCount - time;
138
139        time = System.Environment.TickCount;
140        for (int i = 0; i < repeatTime; i++)
141        {
142            System.IO.MemoryStream ms = new System.IO.MemoryStream();
143            ds.WriteXml(ms);
144            xml = System.Text.UTF8Encoding.UTF8.GetString(ms.ToArray());
145        }
  
146        testReport.SerializeTime = System.Environment.TickCount - time;
147        testReport.SerializedXmlSize = xml.Length;
148
149        time = System.Environment.TickCount;
150        for (int i = 0; i < repeatTime; i++)
151        {
152            System.IO.MemoryStream ms = new System.IO.MemoryStream(System.Text.UTF8Encoding.UTF8.GetBytes(xml));
153            ds.ReadXml(ms);
154            orderDetails = DefaultGateway.CreateList<Order_nbsp_Details_nbsp_Extended>(ds.Tables[0]);
155        }

156        testReport.DeserializeTime = System.Environment.TickCount - time;
157
158        testReport.TotalRunTime = testReport.ReadDataTime + testReport.SerializeTime + testReport.DeserializeTime;
159
160        return testReport;
161    }

162
163    private TestReport DoTest5()
164    {
165        TestReport testReport = new TestReport();
166        testReport.Title = "Entities JSON Serialize";
167
168        time = System.Environment.TickCount;
169        for (int i = 0; i < repeatTime; i++)
170            orderDetails = DefaultGateway.SelectAll<Order_nbsp_Details_nbsp_Extended>();
171        testReport.ReadDataTime = System.Environment.TickCount - time;
172
173        time = System.Environment.TickCount;
174        for (int i = 0; i < repeatTime; i++)
175            xml = SerializeHelper.JsonSerializeEntityArray(orderDetails);
176        testReport.SerializeTime = System.Environment.TickCount - time;
177        testReport.SerializedXmlSize = xml.Length;
178
179        time = System.Environment.TickCount;
180        for (int i = 0; i < repeatTime; i++)
181            orderDetails = SerializeHelper.JsonDeserializeEntityArray<Order_nbsp_Details_nbsp_Extended>(xml);
182        testReport.DeserializeTime = System.Environment.TickCount - time;
183
184        testReport.TotalRunTime = testReport.ReadDataTime + testReport.SerializeTime + testReport.DeserializeTime;
185
186        return testReport;
187    }

188}

更多代码我就不列举了,请自行下载下面的源码。

下载

下载测试框架及源码 (本示例源码包含在新版本的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方式带来的实际的性能提升可能会更大。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值