不论是.net还是xamarin工程里面转换json一直使用的都是Newtonsoft包,一直也没觉得有什么问题
直到最近安卓设备出现了很奇怪的事情,有个方法居然花费了1秒多,定位后发现是Newtonsoft.Json.JsonConvert.DeserializeObject花了1秒多,这我就傻眼了,这玩意怎么处理,要是都这样,之前的工程不可能没发现啊。
于是用.net弄了个单元测试,居然也要120多毫秒,这也太慢了吧。
定义类
1 2 3 4 5 6 | public class testjson { public string aa { get; set; } public string bb { get; set; } public string cc { get; set; } } |
测试:
1 2 3 4 5 6 7 | 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毫秒。
1 2 3 4 5 6 7 8 9 10 | 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秒。
我的想法是,工程启动的时候,随便写个转换先调用下,把第一次的事情做掉,使实际的业务转换受到影响(即使只有第一次)下降到最低。
更多测试,反序列化的和序列化的对比。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | 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的源码再分析,待续....