C# 几个常用 Json 组件的性能测试

上一篇文章中我已经介绍了JsonBuilder方案的整体思路以及一个版本的雏形代码,他现在已经是可以使用的了,但是因为是实时反射的,所以效率并不高。

鉴于几位博友对Json转换组件的性能有兴趣,我先放几个常用组件的测试结果以供参考。下一篇在详细介绍JsonBuilder的优化工作

usingSystem;
usingSystem.Collections.Generic;

///<summary>用户对象
///</summary>
publicclassUser
{
publicstaticUserTestUser()
{//这里我尽量构造一个看上去很复杂的对象,并且这个对象几乎涵盖了所有常用的类型
Useruser=newUser();
user.UID=Guid.NewGuid();
user.Birthday=newDateTime(1986,10,29,18,00,00);
user.IsDeleted=false;
user.Name="blqw";
user.Sex=UserSex.Male;
user.LoginHistory=newList<DateTime>();
user.LoginHistory.Add(DateTime.Today.Add(newTimeSpan(8,00,00)));
user.LoginHistory.Add(DateTime.Today.Add(newTimeSpan(10,10,10)));
user.LoginHistory.Add(DateTime.Today.Add(newTimeSpan(12,33,56)));
user.LoginHistory.Add(DateTime.Today.Add(newTimeSpan(17,25,18)));
user.LoginHistory.Add(DateTime.Today.Add(newTimeSpan(23,06,59)));
user.Info=newUserInfo();
user.Info.Address="广东省广州市";
user.Info.ZipCode=510000;
user.Info.Phone=newDictionary<string,string>();
user.Info.Phone.Add("手机","18688888888");
user.Info.Phone.Add("电话","82580000");
user.Info.Phone.Add("短号","10086");
user.Info.Phone.Add("QQ","21979018");
user.Double=Double.NegativeInfinity;
//user.Self=user;//这里是用来测试循环引用的解析情况
returnuser;
}

publicUserSelf{get;set;}
//Userself
///<summary>唯一ID
///</summary>
publicGuidUID{get;set;}
///<summary>用户名称
///</summary>
publicstringName{get;set;}
///<summary>生日
///</summary>
publicDateTimeBirthday{get;set;}
///<summary>性别
///</summary>
publicUserSexSex{get;set;}
///<summary>是否删除标记
///</summary>
publicboolIsDeleted{get;set;}
///<summary>最近登录记录
///</summary>
publicList<DateTime>LoginHistory{get;set;}
///<summary>联系信息
///</summary>
publicUserInfoInfo{get;set;}
publicDoubleDouble{get;set;}
}
///<summary>用户性别
///</summary>
publicenumUserSex
{
///<summary>男
///</summary>
Male,
///<summary>女
///</summary>
Female
}
///<summary>用户信息
///</summary>
publicclassUserInfo
{
///<summary>地址
///</summary>
publicstringAddress{get;set;}
///<summary>联系方式
///</summary>
publicDictionary<string,string>Phone{get;set;}
///<summary>邮政编码
///</summary>
publicintZipCode{get;set;}
}

测试用例



usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
usingSystem.Diagnostics;
usingSystem.Reflection.Emit;
usingSystem.Data;
usingfastJSON;
usingSystem.IO;
usingSystem.Threading;

namespaceblqw
{
classProgram
{


staticvoidMain(string[]args)
{
intcount=10000;
varobj=User.TestUser();
TestJavaScriptSerializer(count,obj);
TestNewtonsoftJson(count,obj);
TestJayrockJson(count,obj);
TestFastJson(count,obj);
TestQuickJsonBuilder(count,obj);
TestJsonBuilder(count,obj);
}

//测试QuickJsonBuilder性能
staticvoidTestQuickJsonBuilder(intcount,objectobj)
{
Stopwatchsw=newStopwatch();

Console.WriteLine();
Console.WriteLine("QuickJsonBuilder每次"+count+"共10次");
for(intj=0;j<10;j++)
{
sw.Restart();
for(inti=0;i<count;i++)
{
QuickJsonBuilderjb=newQuickJsonBuilder();
jb.ToJson(obj);
}
sw.Stop();
Console.Write(sw.ElapsedMilliseconds+"ms|");
}
Console.WriteLine();
Console.WriteLine("结果:"+newQuickJsonBuilder().ToJson(obj));
Console.WriteLine("==============================================");
}
//测试FastJson性能
staticvoidTestFastJson(intcount,objectobj)
{
Stopwatchsw=newStopwatch();
JSONParametersp=newJSONParameters();
p.EnableAnonymousTypes
=p.IgnoreCaseOnDeserialize
=p.ShowReadOnlyProperties
=p.UseEscapedUnicode
=p.UseExtensions
=p.UseFastGuid
=p.UseOptimizedDatasetSchema
=p.UseUTCDateTime
=p.UsingGlobalTypes
=false;
Console.WriteLine();
Console.WriteLine("fastJSON.NET每次"+count+"共10次");
for(intj=0;j<10;j++)
{
sw.Restart();
for(inti=0;i<count;i++)
{
fastJSON.JSON.Instance.ToJSON(obj,p);
}
sw.Stop();
Console.Write(sw.ElapsedMilliseconds+"ms|");
}

Console.WriteLine();
Console.WriteLine("结果:"+fastJSON.JSON.Instance.ToJSON(obj,p));
Console.WriteLine("==============================================");
}
//测试JayrockJson性能
staticvoidTestJayrockJson(intcount,objectobj)
{
Stopwatchsw=newStopwatch();

Console.WriteLine();
Console.WriteLine("Jayrock.Json每次"+count+"共10次");
for(intj=0;j<10;j++)
{
sw.Restart();
for(inti=0;i<count;i++)
{
varwriter=newJayrock.Json.JsonTextWriter();
Jayrock.Json.Conversion.JsonConvert.Export(obj,writer);
stringstr=writer.ToString();
}
sw.Stop();
Console.Write(sw.ElapsedMilliseconds+"ms|");
}
varw=newJayrock.Json.JsonTextWriter();
Jayrock.Json.Conversion.JsonConvert.Export(obj,w);

Console.WriteLine();
Console.WriteLine("结果:"+w.ToString());
Console.WriteLine("==============================================");
}

staticvoidTestNewtonsoftJson(intcount,objectobj)
{
Stopwatchsw=newStopwatch();

Console.WriteLine();
Console.WriteLine("Newtonsoft.Json每次"+count+"共10次");
for(intj=0;j<10;j++)
{
sw.Restart();
for(inti=0;i<count;i++)
{
Newtonsoft.Json.JsonConvert.SerializeObject(obj);
}
sw.Stop();
Console.Write(sw.ElapsedMilliseconds+"ms|");
}
varw=Newtonsoft.Json.JsonConvert.SerializeObject(obj);

Console.WriteLine();
Console.WriteLine("结果:"+w.ToString());
Console.WriteLine("==============================================");
}

staticvoidTestJavaScriptSerializer(intcount,objectobj)
{


Stopwatchsw=newStopwatch();

Console.WriteLine();
Console.WriteLine("JavaScriptSerializer每次"+count+"共10次");
for(intj=0;j<10;j++)
{
sw.Restart();
for(inti=0;i<count;i++)
{
newSystem.Web.Script.Serialization.JavaScriptSerializer().Serialize(obj);
}
sw.Stop();
Console.Write(sw.ElapsedMilliseconds+"ms|");
}
varw=newSystem.Web.Script.Serialization.JavaScriptSerializer().Serialize(obj);

Console.WriteLine();
Console.WriteLine("结果:"+w.ToString());
Console.WriteLine("==============================================");
}

//测试JsonBuilder性能
staticvoidJsonBuilder(intcount,objectobj)
{
Stopwatchsw=newStopwatch();

Console.WriteLine();
Console.WriteLine("QuickJsonBuilder每次"+count+"共10次");
for(intj=0;j<10;j++)
{
sw.Reset();
sw.Start();
for(inti=0;i<count;i++)
{
JsonBuilderjb=newJsonBuilder();
jb.ToJsonString(obj);
}
sw.Stop();
Console.Write(sw.ElapsedMilliseconds+"ms|");
}
Console.WriteLine();
Console.WriteLine("结果:"+newJsonBuilder().ToJsonString(obj));
Console.WriteLine("==============================================");
}

}
}

测试代码



测试方案1:微软自带的的JavaScriptSerializer
引用组件:System.Web.Extensions(微软自带了,引用下就好)
stringstr=newSystem.Web.Script.Serialization.JavaScriptSerializer().Serialize(User.TestUser());
//{"Self":null,"UID":"6f50b429-5c13-4875-a29a-e4bd8d7b2772","Name":"blqw","Birthday":"\/Date(530964000000)\/","Sex":0,"IsDeleted":false,"LoginHistory":["\/Date(1377129600000)\/","\/Date(1377137410000)\/","\/Date(1377146036000)\/","\/Date(1377163518000)\/","\/Date(1377184019000)\/"],"Info":{"Address":"广东省广州市","Phone":{"手机":"18688888888","电话":"82580000","短号":"10086","QQ":"21979018"},"ZipCode":510000},"Double":-Infinity}




测试方案2:Newtonsoft.Json
引用组件:Newtonsoft.Json.Net35.dll
stringstr=Newtonsoft.Json.JsonConvert.SerializeObject(User.TestUser());
//{"Self":null,"UID":"6f50b429-5c13-4875-a29a-e4bd8d7b2772","Name":"blqw","Birthday":"\/Date(530964000000+0800)\/","Sex":0,"IsDeleted":false,"LoginHistory":["\/Date(1377129600000+0800)\/","\/Date(1377137410000+0800)\/","\/Date(1377146036000+0800)\/","\/Date(1377163518000+0800)\/","\/Date(1377184019000+0800)\/"],"Info":{"Address":"广东省广州市","Phone":{"手机":"18688888888","电话":"82580000","短号":"10086","QQ":"21979018"},"ZipCode":510000},"Double":-Infinity}



测试方案3:Jayrock.Json
引用组件:Jayrock.Json.dll
JsonTextWriterjtw=newJayrock.Json.JsonTextWriter();
Jayrock.Json.Conversion.JsonConvert.Export(User.TestUser(),jtw);
stringstr=jtw.ToString();
//{"uID":"6f50b429-5c13-4875-a29a-e4bd8d7b2772","name":"blqw","birthday":"1986-10-29T18:00:00.0000000+08:00","sex":"Male","isDeleted":false,"loginHistory":["2013-08-22T08:00:00.0000000+08:00","2013-08-22T10:10:10.0000000+08:00","2013-08-22T12:33:56.0000000+08:00","2013-08-22T17:25:18.0000000+08:00","2013-08-22T23:06:59.0000000+08:00"],"info":{"address":"广东省广州市","phone":{"手机":"18688888888","电话":"82580000","短号":"10086","QQ":"21979018"},"zipCode":510000},"double":-Infinity}



测试方案4:fastJSON.NET
引用组件:fastJSON.dll
JSONParametersp=newJSONParameters();
p.EnableAnonymousTypes
=p.IgnoreCaseOnDeserialize
=p.ShowReadOnlyProperties
=p.UseEscapedUnicode
=p.UseExtensions
=p.UseFastGuid
=p.UseOptimizedDatasetSchema
=p.UseUTCDateTime
=p.UsingGlobalTypes
=false;//所有参数为false,执行速度最快

stringstr=fastJSON.JSON.Instance.ToJSON(User.TestUser(),p);
//{"Self":null,"UID":"6f50b429-5c13-4875-a29a-e4bd8d7b2772","Name":"blqw","Birthday":"1986-10-2918:00:00","Sex":"Male","IsDeleted":false,"LoginHistory":["2013-08-2208:00:00","2013-08-2210:10:10","2013-08-2212:33:56","2013-08-2217:25:18","2013-08-2223:06:59"],"Info":{"Address":"广东省广州市","Phone":{"手机":"18688888888","电话":"82580000","短号":"10086","QQ":"21979018"},"ZipCode":510000},"Double":-Infinity}



测试方案5,6:QuickJsonBuilder,JsonBuilder
ps:以上几种类型都不支持循环引用,如果有,直接抛出异常
说明:QuickJsonBuilder就是我上篇中介绍的JsonBuilder的终极形态

QuickJsonBuilderjb=newQuickJsonBuilder();
jb.ToJson(User.TestUser());
//{"Self":null,"UID":"6f50b429-5c13-4875-a29a-e4bd8d7b2772","Name":"blqw","Birthday":"1986-10-2918:00:00","Sex":"Male","IsDeleted":false,"LoginHistory":["2013-08-2208:00:00","2013-08-2210:10:10","2013-08-2212:33:56","2013-08-2217:25:18","2013-08-2223:06:59"],"Info":{"Address":"广东省广州市","Phone":{"手机":"18688888888","电话":"82580000","短号":"10086","QQ":"21979018"},"ZipCode":510000},"Double":-Infinity}
ps:当Self指向自己本身的时候,将返回"Self":undefined用以区分空对象



测试方案7:ServiceStack.Text
引用组件:ServiceStack.Text.dll抱歉我只找到4.0的
这个是后来补上的,测试代码中没有这个...

User.TestUser().ToJson();
//{"UID":"48d4624ad0c8475094d00fc769c7129f","Name":"blqw","Birthday":"\/Date(530964000000+0800)\/","Sex":"Male","IsDeleted":false,"LoginHistory":["\/Date(1377129600000+0800)\/","\/Date(1377137410000+0800)\/","\/Date(1377146036000+0800)\/","\/Date(1377163518000+0800)\/","\/Date(1377184019000+0800)\/"],"Info":{"Address":"广东省广州市","Phone":{"手机":"18688888888","电话":"82580000","短号":"10086","QQ":"21979018"},"ZipCode":510000},"Double":-Infinity}
ps:依然不支持循环引用,抛出堆栈异常

测试结果(单位"毫秒")
 
循环次数 测试组件 第一轮 第二轮 第三轮 第四轮 第五轮
1次  JavaScriptSerializer  12
 0  0  0  0
 Newtonsoft.Json  208  0  0  0  0
 Jayrock.Json  85  0  0  0  0
 fastJSON.NET  47  0  0  0  0
 QuickJsonBuilder  37  0  0  0  0
 JsonBuilder  22  0  0  0  0
ServiceStack.Text  138  0  0  0  0
100次  JavaScriptSerializer  23  7  7  8  7
 Newtonsoft.Json  201  2  3  2  2
 Jayrock.Json  77  8  9  9  8
 fastJSON.NET  41  1  1  1  1
 QuickJsonBuilder  36  1  1  1  1
 JsonBuilder  26  3  4  3  3
ServiceStack.Text  139  2  2  2  2
10000次  JavaScriptSerializer  765  751  752  751  749
 Newtonsoft.Json  437  253  251  248  243
 Jayrock.Json  967  905  965  913  952
 fastJSON.NET  239  181  200  167  166
 QuickJsonBuilder  171  128  132  136  129
 JsonBuilder  418  386  388  391  360
ServiceStack.Text  367  216  224  238  223

测试结果仅供参考

 

总结

可以看出基本所有组件在第一轮用时都是最长的,应该是在处理一些初始化和缓存的工作。

所以呢,我特别给出了1次的循环结果,

JavaScriptSerializer 可以看出在100次以内的时候微软的还是有一些优势的,随着次数增加性能就渐渐跟不上了

Newtonsoft.Json一直表现平平啊,没有特别突出就地方,就跟JsonBuilder比性能也没有好到那里去

Jayrock.Json 是昨天一位博友告诉我的,据说是淘宝sdk在用的,性能只能说,好差。。。

fastJSON.NET 确实是所有组件中最快的,QuickJsonBuilder也从中借鉴了一些处理方式

ServiceStack.Text 中规中矩吧比Newtonsoft.Json好一点点.就是我只找到4.0的拓展方法,不知道2.0下有没有相应的组件

好吧 我自己的组件我就不做评价了

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。