Newtonsoft.Json.JsonConvert.DeserializeObject首次轉換太慢問題

不論是.net還是xamarin工程裏面轉換json一直使用的都是Newtonsoft包,一直也沒覺得有什麼問題

直到最近安卓設備出現了很奇怪的事情,有個方法居然花費了1秒多,定位後發現是Newtonsoft.Json.JsonConvert.DeserializeObject花了1秒多,這我就傻眼了,這玩意怎麼處理,要是都這樣,之前的工程不可能沒發現啊。

於是用.net弄了個單元測試,居然也要120多毫秒,這也太慢了吧。

 定義類

        public class testjson
        {
            public string aa { get; set; }
            public string bb { get; set; }
            public string cc { get; set; }
        }

測試:

            string output = "{ \"aa\":\"1\",\"bb\":\"哈哈哈哈\",\"cc\":\"和hi黑欸\"} ";
            DateTime start = DateTime.Now;
            testjson res = new testjson();
            object a = Newtonsoft.Json.JsonConvert.DeserializeObject(output, typeof(testjson));
            DateTime end = DateTime.Now;
            TimeSpan bbbb = end - start;
            Console.WriteLine("第一次轉換一次花費時間:" + bbbb.TotalMilliseconds);

去網上找了找,看到一些json轉換的插件對比測試,Newtonsoft沒有這麼差啊。做個循環測試,跑個10000次,結果只要26毫秒。

            DateTime start1 = DateTime.Now;
            for (int i = 0; i < 10000; i++)
            {
                string output1 = "{ \"aa\":\"1\",\"bb\":\"哈哈哈哈\",\"cc\":\"和hi黑欸\"} ";
                testjson res1 = new testjson();
                res1 = (testjson)Newtonsoft.Json.JsonConvert.DeserializeObject(output1, typeof(testjson));
            }
            DateTime end1 = DateTime.Now;
            TimeSpan bbbb1 = end1 - start1;
            Console.WriteLine("第二次轉換10000次花費時間:" + bbbb1.TotalMilliseconds);

進一步測試,換了個類來轉換,同樣10000次,只要23毫秒。

換到垃圾安卓板上去測試, 第一次轉換1.7秒,接着循環10000次620毫秒。

所以基本可以確定,首次調用  Newtonsoft.Json.JsonConvert.DeserializeObject的時候,會比較慢。

如果沒有單獨調用第一次,直接循環10000次,就算花費145毫秒,估計也不會發現其中第一次耗費了120秒。

我的想法是,工程啓動的時候,隨便寫個轉換先調用下,把第一次的事情做掉,使實際的業務轉換受到影響(即使只有第一次)下降到最低。

更多測試,反序列化的和序列化的對比。

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
namespace UnitTestProject1
{
    [TestClass]
    public class UnitTest1
    {
      [TestMethod]
        public void TestMethod1()
        {
            int counts = 10000;
            DateTime t1 = DateTime.Now;
            DateTime t2 = DateTime.Now;

            string output = "{ \"aa\":\"1\",\"bb\":\"哈哈哈哈\",\"cc\":\"\"} ";
            t1 = DateTime.Now;

            testjson res = (testjson)Newtonsoft.Json.JsonConvert.DeserializeObject(output, typeof(testjson));
            t2 = DateTime.Now;

            Console.WriteLine($"第1次反序列化花費時間:{(t2 - t1).TotalMilliseconds}");

            //string output = "{ \"flag\":\"1\",\"cause\":\"\",\"data\":{ \"aac004\":\"1\",\"ake007\":\"20200226\",\"aac003\":\"黃方金\",\"fplist\":[{\"bkc011\":\"0\",\"bkc010\":\"0\",\"aae072\":\"YD027088915\",\"aka063_mc\":\"診察費\",\"akc227\":\"17\",\"aaa027\":\"350200\",\"aka063\":\"06\",\"bkc008\":\"17\",\"bkc009\":\"0\"},{\"bkc011\":\".2\",\"bkc010\":\"0\",\"aae072\":\"YD027088915\",\"aka063_mc\":\"檢查費\",\"akc227\":\"137.2\",\"aaa027\":\"350200\",\"aka063\":\"08\",\"bkc008\":\"111\",\"bkc009\":\"26\"}],\"mzlist\":[{\"bka542_mc\":\"其中公務員醫療補助\",\"bka542\":\"bkc059_1\",\"bkeb34\":\"0.0\"}],\"akc227\":\"154.2\",\"bkc014\":\"20200226\",\"bke174_mc\":\"省內異地\",\"aac999\":\"350426198801111010\",\"bkc171\":\"1002\",\"aaz149\":\"000000000000\",\"akc190\":\"YD024926537\",\"bkc075\":\"0\",\"amc028\":\"0\",\"bkc059\":\"0\",\"ake026\":\"0\",\"aab004\":\"廈門翼號網絡服務有限公司\",\"amc020\":\"0\",\"aka150\":\"4\",\"bke174\":\"1\",\"bkc052\":\"0\",\"aac002\":\"350426198801111010\",\"bae029\":\"1002\",\"bmc041\":\"0\",\"bkc591\":\"0\",\"aaz500\":\"D74781764\",\"bkc102\":\"0\",\"aae072\":\"YD027088915\",\"aae011\":\"lh_hsj\",\"bkc041\":\"154.2\",\"akc087\":\"0\",\"bkc040\":\"0\",\"bkc045\":\"0\",\"bkc062\":\"0\",\"ake173\":\"0\",\"bkc060\":\"0\"},\"traceid\":\"\"}";
            t1 = DateTime.Now;
            testjson item = new testjson()
            {
                aa = "aljfdlsjflkjsdlf",
                bb = "sdfsdfsdfds啊哈哈的撒發",
                cc = "af;djaf;lkdsjf"
            };



            string mmm = Newtonsoft.Json.JsonConvert.SerializeObject(item);
            t2 = DateTime.Now;
            Console.WriteLine("第1次序列化花費時間:" + (t2 - t1).TotalMilliseconds);

            t1 = DateTime.Now;
            for (int i = 0; i < counts; i++)
            {
                string output1 = "{ \"aa\":\"1\",\"bb\":\"哈哈哈哈\",\"cc\":\"和hi黑欸\"} ";
                testjson res1 = new testjson();
                res1 = (testjson)Newtonsoft.Json.JsonConvert.DeserializeObject(output1, typeof(testjson));
            }
            t2 = DateTime.Now;

            Console.WriteLine($"第2次反序列化{counts}次花費時間:{(t2 - t1).TotalMilliseconds}");


            t1 = DateTime.Now;
            for (int i = 0; i < counts; i++)
            {
                string nnnnn = Newtonsoft.Json.JsonConvert.SerializeObject(item);
            }
            t2 = DateTime.Now;

            Console.WriteLine($"第2次序列化{counts}次花費時間:{(t2 - t1).TotalMilliseconds}");

            t1 = DateTime.Now;
            for (int i = 0; i < counts; i++)
            {
                if (i % 2 == 1)
                {
                    string output2 = "{ \"aaaa\":\"1\",\"bbb\":\"哈哈哈哈\",\"ccc\":\"和hi黑欸\"} ";
                    testjson2 res2 = new testjson2();
                    res2 = (testjson2)Newtonsoft.Json.JsonConvert.DeserializeObject(output2, typeof(testjson2));
                }
                else
                {
                    string output1 = "{ \"aa\":\"1\",\"bb\":\"哈哈哈哈\",\"cc\":\"和hi黑欸\"} ";
                    testjson res1 = new testjson();
                    res1 = (testjson)Newtonsoft.Json.JsonConvert.DeserializeObject(output1, typeof(testjson));
                }
            }
            t2 = DateTime.Now;

            Console.WriteLine($"第2次反序列化{counts}次(反覆切換類),花費時間:{(t2 - t1).TotalMilliseconds}");
         

        }


        public class testjson
        {
            public string aa { get; set; }
            public string bb { get; set; }
            public string cc { get; set; }

        }

        public class testjson2
        {
            public string aaa { get; set; }
            public string bbb { get; set; }
            public string ccc { get; set; }

        }
    }
}

測試結果:首次反序列化都要120毫秒,首次序列化也要20多毫秒,反過先做序列化也是首次120毫秒左右,首次反序列化20毫秒左右。再後續一萬次的時間也只要20毫秒左右,序列化相對來說比反序列化要快一些。

也就是說 jsonconvert "首次"調用的時候可能在100毫秒左右,然後"首次"調用序列化或者反序列化需要20毫秒左右,再往後的調用耗時就幾乎可以忽略不計了。

 

目前我的猜想是首次調用做了一些初始化的工作,具體的後續去看下newtonsoftd的源碼再分析,待續....

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章