您的位置:首页 > Web前端 > JavaScript

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

2006-04-18 16:40 603 查看
本文以一组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方式带来的实际的性能提升可能会更大。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息