今天在做blqw.Json反序列化的優化工作的時候發現一個問題,在反序列化一個非常簡單的對象
public class SimpleObject { public static SimpleObject New() { return new SimpleObject { Scores = new int[]{1,2,3,4,5,6,7,8,9,0} }; } public int[] Scores { get; set; } }
在性能上我居然和想象中的相差非常大,看結果

我第一時間想到的就是會不會Dictionary引起的?
delegate bool TryParseHandler(bool nullable, string str, out object value); Dictionary<TypeCode, TryParseHandler> TryParseMethods = new Dictionary<TypeCode, TryParseHandler>(); protected JsonConvert() { if (Instance == null) { TryParseMethods = new Dictionary<TypeCode, TryParseHandler>(); TryParseMethods.Add(Type.GetTypeCode(typeof(Boolean)), TryParseBoolean); TryParseMethods.Add(Type.GetTypeCode(typeof(Byte)), TryParseByte); TryParseMethods.Add(Type.GetTypeCode(typeof(Char)), TryParseChar); TryParseMethods.Add(Type.GetTypeCode(typeof(DateTime)), TryParseDateTime); TryParseMethods.Add(Type.GetTypeCode(typeof(Decimal)), TryParseDecimal); TryParseMethods.Add(Type.GetTypeCode(typeof(Double)), TryParseDouble); TryParseMethods.Add(Type.GetTypeCode(typeof(Int16)), TryParseInt16); TryParseMethods.Add(Type.GetTypeCode(typeof(Int32)), TryParseInt32); TryParseMethods.Add(Type.GetTypeCode(typeof(Int64)), TryParseInt64); TryParseMethods.Add(Type.GetTypeCode(typeof(SByte)), TryParseSByte); TryParseMethods.Add(Type.GetTypeCode(typeof(Single)), TryParseSingle); TryParseMethods.Add(Type.GetTypeCode(typeof(UInt16)), TryParseUInt16); TryParseMethods.Add(Type.GetTypeCode(typeof(UInt32)), TryParseUInt32); TryParseMethods.Add(Type.GetTypeCode(typeof(UInt64)), TryParseUInt64); TryParseMethods.Add(Type.GetTypeCode(typeof(Guid)), TryParseGuid); TryParseMethods.Add(Type.GetTypeCode(typeof(String)), TryParseString); } else { TryParseMethods = Instance.TryParseMethods; } } public bool TryParse(Type type, string str, out object value) { bool nullable; //處理可空值類型 Type t; t = Nullable.GetUnderlyingType(type); if (t != null) { nullable = true; type = t; } else { nullable = false; } TryParseHandler tryparse; if (TryParseMethods.TryGetValue(Type.GetTypeCode(type), out tryparse)) { return tryparse(nullable, str, out value); } else { value = null; return false; } }
我直接改成了switch,我要查看最壞情況下的性能,所以把int32的case分支放到的最下面
switch (Type.GetTypeCode(type)) { case TypeCode.Boolean: return TryParseBoolean(nullable, str, out value); case TypeCode.Byte: return TryParseByte(nullable, str, out value); case TypeCode.Char: return TryParseChar(nullable, str, out value); case TypeCode.DateTime: return TryParseDateTime(nullable, str, out value); case TypeCode.Decimal: return TryParseDecimal(nullable, str, out value); case TypeCode.Double: return TryParseDouble(nullable, str, out value); case TypeCode.Int16: return TryParseInt16(nullable, str, out value); case TypeCode.Int64: return TryParseInt64(nullable, str, out value); case TypeCode.SByte: return TryParseSByte(nullable, str, out value); case TypeCode.Single: return TryParseSingle(nullable, str, out value); case TypeCode.String: return TryParseString(nullable, str, out value); case TypeCode.UInt16: return TryParseUInt16(nullable, str, out value); case TypeCode.UInt32: return TryParseUInt32(nullable, str, out value); case TypeCode.UInt64: return TryParseUInt64(nullable, str, out value); case TypeCode.DBNull: case TypeCode.Empty: value = null; return str == "null" || str == "undefined" || str == null; case TypeCode.Int32: return TryParseInt32(nullable, str, out value); case TypeCode.Object: default: value = null; return false; }
幾乎是沒有什么差別的

所以我果斷放棄了Dictionary,我可以把常用的類型(int,string,double等)放到前面,即使最差情況也和Dictionary一樣,大部分情況下都會比Dictionary好
接着我就想會不會是因為我多處理了一個可空值類型,所以性能上會比fastJson慢?(fastJson在反序列化可空值類型的時候是報錯的)
然后我把處理可控制類型的地方給注釋了,看看到底是不是判斷可空值類型的時候引起的
bool nullable; //處理可空值類型 //Type t; //t = Nullable.GetUnderlyingType(type); //if (t != null) //{ // nullable = true; // type = t; //} //else { nullable = false; }

結果幾乎沒有變化!!!
嗯,我把TryParseInt32(nullable, str, out value);中處理可控制類型的方法也注釋了試試
public virtual bool TryParseInt32(bool nullable, string str, out object value) { Int32 v; if (Int32.TryParse(str, out v)) { //value = nullable ? new Nullable<Int32>(v) : v; value = v; return true; } else { value = null; return false; } }
我了個去,性能真的提高了!!

但是非常奇怪的是,我以前做過測試,判斷是幾乎不消耗性能的,為什么區區10W次的判斷能相差10多毫秒??
難道問題在三元表達式???
我試着把三元表達式改成if..else...
public virtual bool TryParseInt32(bool nullable, string str, out object value) { Int32 v; if (Int32.TryParse(str, out v)) { if (nullable) { value = new Nullable<Int32>(v); } else { value = v; } return true; } else { value = null; return false; } }
尼瑪坑爹了好嗎!!!!

改成if...else...之后完全和之前的一模一樣啊...
三元表達式這是想表達什么呢?


