不論是.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的源碼再分析,待續....