不论是.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的源码再分析,待续....