学习笔记1:性能问题在于你想不到的任何地方!
今天在做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...之后完全和之前的一模一样啊...
三元表达式这是想表达什么呢?
我写的文章,除了纯代码,其他的都是想表达一种思想,一种解决方案.希望各位看官不要局限于文章中的现成的代码,要多关注整个文章的主题思路,谢谢!
我发布的代码,没有任何版权,遵守WTFPL协议(如有引用,请遵守被引用代码的协议)
qq群:5946699 希望各位喜爱C#的朋友可以在这里交流学习,分享编程的心得和快乐
我发布的代码,没有任何版权,遵守WTFPL协议(如有引用,请遵守被引用代码的协议)
qq群:5946699 希望各位喜爱C#的朋友可以在这里交流学习,分享编程的心得和快乐