幾個經常使用Json組件的性能測試

上一篇文章中我已經介紹了JsonBuilder方案的總體思路以及一個版本的雛形代碼,他如今已是可使用的了,可是由於是實時反射的,因此效率並不高。html

鑑於幾位博友對Json轉換組件的性能有興趣,我先放幾個經常使用組件的測試結果以供參考。下一篇在詳細介紹JsonBuilder的優化工做緩存

  測試用例ide

using System;
using System.Collections.Generic;

/// <summary> 用戶對象
/// </summary>
public class User
{
    public static User TestUser()
    {//這裏我儘可能構造一個看上去很複雜的對象,而且這個對象幾乎涵蓋了全部經常使用的類型
        User user = new User();
        user.UID = Guid.NewGuid();
        user.Birthday = new DateTime(1986, 10, 29, 18, 00, 00);
        user.IsDeleted = false;
        user.Name = "blqw";
        user.Sex = UserSex.Male;
        user.LoginHistory = new List<DateTime>();
        user.LoginHistory.Add(DateTime.Today.Add(new TimeSpan(8, 00, 00)));
        user.LoginHistory.Add(DateTime.Today.Add(new TimeSpan(10, 10, 10)));
        user.LoginHistory.Add(DateTime.Today.Add(new TimeSpan(12, 33, 56)));
        user.LoginHistory.Add(DateTime.Today.Add(new TimeSpan(17, 25, 18)));
        user.LoginHistory.Add(DateTime.Today.Add(new TimeSpan(23, 06, 59)));
        user.Info = new UserInfo();
        user.Info.Address = "廣東省廣州市";
        user.Info.ZipCode = 510000;
        user.Info.Phone = new Dictionary<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; //這裏是用來測試循環引用的解析狀況
        return user;
    }

    public User Self { get; set; }
    //User self
    /// <summary> 惟一ID
    /// </summary>
    public Guid UID { get; set; }
    /// <summary> 用戶名稱
    /// </summary>
    public string Name { get; set; }
    /// <summary> 生日
    /// </summary>
    public DateTime Birthday { get; set; }
    /// <summary> 性別
    /// </summary>
    public UserSex Sex { get; set; }
    /// <summary> 是否刪除標記
    /// </summary>
    public bool IsDeleted { get; set; }
    /// <summary> 最近登陸記錄
    /// </summary>
    public List<DateTime> LoginHistory { get; set; }
    /// <summary> 聯繫信息
    /// </summary>
    public UserInfo Info { get; set; }
    public Double Double { get; set; }
}
/// <summary> 用戶性別
/// </summary>
public enum UserSex
{
    /// <summary>/// </summary>
    Male,
    /// <summary>/// </summary>
    Female
}
/// <summary> 用戶信息
/// </summary>
public class UserInfo
{
    /// <summary> 地址
    /// </summary>
    public string Address { get; set; }
    /// <summary> 聯繫方式
    /// </summary>
    public Dictionary<string, string> Phone { get; set; }
    /// <summary> 郵政編碼
    /// </summary>
    public int ZipCode { get; set; }
}
測試用例
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Reflection.Emit;
using System.Data;
using fastJSON;
using System.IO;
using System.Threading;

namespace blqw
{
    class Program
    {


        static void Main(string[] args)
        {
            int count = 10000;
            var obj = User.TestUser();
            TestJavaScriptSerializer(count, obj);
            TestNewtonsoftJson(count, obj);
            TestJayrockJson(count, obj);
            TestFastJson(count, obj);
            TestQuickJsonBuilder(count, obj);
            TestJsonBuilder(count, obj);
        }

        //測試QuickJsonBuilder性能
        static void TestQuickJsonBuilder(int count, object obj)
        {
            Stopwatch sw = new Stopwatch();

            Console.WriteLine();
            Console.WriteLine("QuickJsonBuilder 每次" + count + " 共10次");
            for (int j = 0; j < 10; j++)
            {
                sw.Restart();
                for (int i = 0; i < count; i++)
                {
                    QuickJsonBuilder jb = new QuickJsonBuilder();
                    jb.ToJson(obj);
                }
                sw.Stop();
                Console.Write(sw.ElapsedMilliseconds + "ms | ");
            }
            Console.WriteLine();
            Console.WriteLine("結果:" + new QuickJsonBuilder().ToJson(obj));
            Console.WriteLine("==============================================");
        }
        //測試FastJson性能
        static void TestFastJson(int count, object obj)
        {
            Stopwatch sw = new Stopwatch();
            JSONParameters p = new JSONParameters();
            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 (int j = 0; j < 10; j++)
            {
                sw.Restart();
                for (int i = 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性能
        static void TestJayrockJson(int count, object obj)
        {
            Stopwatch sw = new Stopwatch();

            Console.WriteLine();
            Console.WriteLine("Jayrock.Json 每次" + count + " 共10次");
            for (int j = 0; j < 10; j++)
            {
                sw.Restart();
                for (int i = 0; i < count; i++)
                {
                    var writer = new Jayrock.Json.JsonTextWriter();
                    Jayrock.Json.Conversion.JsonConvert.Export(obj, writer);
                    string str = writer.ToString();
                }
                sw.Stop();
                Console.Write(sw.ElapsedMilliseconds + "ms | ");
            }
            var w = new Jayrock.Json.JsonTextWriter();
            Jayrock.Json.Conversion.JsonConvert.Export(obj, w);

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

        static void TestNewtonsoftJson(int count, object obj)
        {
            Stopwatch sw = new Stopwatch();

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

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

        static void TestJavaScriptSerializer(int count, object obj)
        {


            Stopwatch sw = new Stopwatch();

            Console.WriteLine();
            Console.WriteLine("JavaScriptSerializer 每次" + count + " 共10次");
            for (int j = 0; j < 10; j++)
            {
                sw.Restart();
                for (int i = 0; i < count; i++)
                {
                    new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(obj);
                }
                sw.Stop();
                Console.Write(sw.ElapsedMilliseconds + "ms | ");
            }
            var w = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(obj);

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

        //測試JsonBuilder性能
        static void JsonBuilder(int count, object obj)
        {
            Stopwatch sw = new Stopwatch();

            Console.WriteLine();
            Console.WriteLine("QuickJsonBuilder 每次" + count + " 共10次");
            for (int j = 0; j < 10; j++)
            {
                sw.Reset();
                sw.Start();
                for (int i = 0; i < count; i++)
                {
                    JsonBuilder jb = new JsonBuilder();
                    jb.ToJsonString(obj);
                }
                sw.Stop();
                Console.Write(sw.ElapsedMilliseconds + "ms | ");
            }
            Console.WriteLine();
            Console.WriteLine("結果:" + new JsonBuilder().ToJsonString(obj));
            Console.WriteLine("==============================================");
        }

    }
}
測試代碼

  測試方案1:微軟自帶的的 JavaScriptSerializer性能

引用組件:System.Web.Extensions(微軟自帶了,引用下就好)測試

string str = new System.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.dllui

string str = 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.dllspa

JsonTextWriter jtw = new Jayrock.Json.JsonTextWriter();
Jayrock.Json.Conversion.JsonConvert.Export(User.TestUser(), jtw);
string str = 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.NETpwa

引用組件:fastJSON.dll

JSONParameters p = new JSONParameters();
p.EnableAnonymousTypes
    = p.IgnoreCaseOnDeserialize
    = p.ShowReadOnlyProperties
    = p.UseEscapedUnicode
    = p.UseExtensions
    = p.UseFastGuid
    = p.UseOptimizedDatasetSchema
    = p.UseUTCDateTime
    = p.UsingGlobalTypes
    = false;//全部參數爲false,執行速度最快

string str = fastJSON.JSON.Instance.ToJSON(User.TestUser(), p);
//{"Self":null,"UID":"6f50b429-5c13-4875-a29a-e4bd8d7b2772","Name":"blqw","Birthday":"1986-10-29 18:00:00","Sex":"Male","IsDeleted":false,"LoginHistory":["2013-08-22 08:00:00","2013-08-22 10:10:10","2013-08-22 12:33:56","2013-08-22 17:25:18","2013-08-22 23:06:59"],"Info":{"Address":"廣東省廣州市","Phone":{"手機":"18688888888","電話":"82580000","短號":"10086","QQ":"21979018"},"ZipCode":510000},"Double":-Infinity}

  測試方案5,6:QuickJsonBuilder,JsonBuilder

ps:以上幾種類型都不支持循環引用,若是有,直接拋出異常

說明:QuickJsonBuilder就是我上篇中介紹的JsonBuilder的終極形態

QuickJsonBuilder jb = new QuickJsonBuilder();
jb.ToJson(User.TestUser());
//{"Self":null,"UID":"6f50b429-5c13-4875-a29a-e4bd8d7b2772","Name":"blqw","Birthday":"1986-10-29 18:00:00","Sex":"Male","IsDeleted":false,"LoginHistory":["2013-08-22 08:00:00","2013-08-22 10:10:10","2013-08-22 12:33:56","2013-08-22 17:25:18","2013-08-22 23: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下有沒有相應的組件

好吧 我本身的組件我就不作評價了

相關文章
相關標籤/搜索