程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 重復造輪子感悟 – XLinq性能提升心得,xlinq性能提升

重復造輪子感悟 – XLinq性能提升心得,xlinq性能提升

編輯:C#入門知識

重復造輪子感悟 – XLinq性能提升心得,xlinq性能提升


曾經的兩座大山

1、EF

剛接觸linq那段時間,感覺這家伙好神奇,語法好優美,好厲害。後來經歷了EF一些不如意的地方,就想去彌補,既然想彌補,就必須去了解原理。最開始甚至很長一段時間都搞不懂IQueryProvider(小聲說,其實現在也沒完全搞懂),好不容易把IQueryProvider搞懂了,然後才發現好戲才剛剛開始,這個時候嘗試寫了第一個ORM。那個時候不明白表達式樹的原理,自然一開始的思路就是走一點算一點,走到後面就沒法走了,因為思路太亂了。這個時候就感覺EF太牛了,那麼復雜的linq都能翻譯出來,雖然翻譯的sql的質量不行,而且還有坑,不過至少翻譯出來了,感覺自己永遠都沒辦法做到。

2、Dapper

這框架是大名鼎鼎的,性能是相當高的,底層是用EMIT寫的。然而我這人就是有技術潔癖,如果是我自己一個人開發,那麼如果這個工具讓我感覺到了不爽,我就會嘗試自己開發。所以我也沒用dapper,原因只是它直接操作了Connection,而且要手寫sql代碼。但是我自己寫的在性能上始終是個硬傷,跟dapper比不了。之前我業余用表達式樹實現了DataSet到List的轉換,然後拿到公司裝逼,同事來了一句"來來咱跟dapper比比",我說"得得你就別虐我了成不",比的結果當然是比較慘的,那個時候我覺得我不可能達到dapper的轉換速度。

性能提升測試

測試代碼

測試結果

秒EF是妥妥的,但dapper基本上性能一樣,那點差距就直接忽略吧。

之前也進行過一次,被dapper秒,和EF性能一樣,原因是因為字典緩存用的有問題。

而這次這個最終取數據全部用的數組,一開始其實把dapper都給秒了,快了dapper接近一半,不過後來發現情況沒考慮全,考慮全了就差不多了。

感悟和心得

IDataReader轉List關鍵代碼

1 public static Func<IDataReader, IList> GetDataReaderMapeer(Type type,IDataReader reader) 2 { 3 Func<IDataReader, IList> func = null; 4 if (!_dataReader2ListCahce.TryGetValue(type, out func)) 5 { 6 lock (_dataReader2ListCahce) 7 { 8 if (!_dataReader2ListCahce.TryGetValue(type, out func)) 9 { 10 var readerExp = Expression.Parameter(ReflectorConsts.IDataReaderType, "reader"); 11 var properties = ExpressionReflector.GetProperties(type); 12 var fieldCount = reader.FieldCount; 13 var expressions = new List<Expression>(); 14 var objVar = Expression.Variable(type, "entity"); 15 var fieldCountVar = Expression.Variable(ReflectorConsts.Int32Type, "fieldCount"); 16 var readerVar = Expression.Variable(ReflectorConsts.IDataReaderType, "readerVar"); 17 var propertyNameArr = Expression.Variable(ReflectorConsts.StringArrayType, "pis"); 18 var indexArrVar = Expression.Variable(ReflectorConsts.Int32ArrayType, "indexes"); 19 var readIndexVar = Expression.Variable(ReflectorConsts.Int32Type, "readIndex"); 20 var indexVar = Expression.Variable(ReflectorConsts.Int32Type, "index"); 21 var forBreakLabel = Expression.Label("forBreak"); 22 var assignIndexVar = Expression.Assign(indexVar, Expression.Constant(0)); 23 var listType = ReflectorConsts.ListType.MakeGenericType(type); 24 var listVar = Expression.Variable(listType, "list"); 25 expressions.Add(Expression.Assign(listVar, Expression.New(listType))); 26 expressions.Add(Expression.Assign(readerVar, readerExp)); 27 expressions.Add(assignIndexVar); 28 var assignFieldCountVar = Expression.Assign(fieldCountVar, 29 Expression.MakeMemberAccess(readerVar, ReflectorConsts.FieldCountOfIDataReader) 30 ); 31 expressions.Add(assignFieldCountVar); 32 var readNameExp = Expression.Call(readerVar, ReflectorConsts.GetOrdinalOfIDataReader, Expression.ArrayIndex(propertyNameArr, indexVar)); 33 var initIndexArray = Expression.Assign(indexArrVar, Expression.NewArrayBounds(ReflectorConsts.Int32Type, Expression.Constant(fieldCount))); 34 var initPropertyArrayExpressions = new List<Expression>(); 35 for (int i = 0; i < fieldCount; i++) 36 { 37 initPropertyArrayExpressions.Add(Expression.Constant(reader.GetName(i))); 38 } 39 var initPropertyArray = Expression.Assign(propertyNameArr, Expression.NewArrayInit(ReflectorConsts.StringType, initPropertyArrayExpressions)); 40 var assignIndexArrayVar = Expression.Assign(Expression.ArrayAccess(indexArrVar, indexVar), readNameExp); 41 expressions.Add(initPropertyArray); 42 expressions.Add(initIndexArray); 43 expressions.Add(Expression.Loop( 44 Expression.IfThenElse( 45 Expression.LessThan(indexVar, fieldCountVar), 46 Expression.Block( 47 assignIndexArrayVar, 48 Expression.Assign( 49 indexVar, 50 Expression.Add(indexVar, Expression.Constant(1)) 51 ) 52 ), 53 Expression.Break(forBreakLabel) 54 ), 55 forBreakLabel 56 )); 57 Expression body = null; 58 DataReaderGetMethodSwitcher switcher = null; 59 var labelTarget = Expression.Label(type, "return"); 60 var paramterExpressions = new List<ParameterExpression>(); 61 var setEntityExpressions = new List<Expression>(); 62 if (TypeHelper.IsCompilerGenerated(type)) 63 { 64 var constructor = type.GetConstructors().FirstOrDefault(); 65 if (constructor == null) 66 { 67 throw new ArgumentException("類型" + type.FullName + "未找到構造方法"); 68 } 69 var parameters = constructor.GetParameters(); 70 var expressionParams = new List<ParameterExpression>(); 71 for (int i = 0; i < fieldCount; i++) 72 { 73 var parameter = parameters[i]; 74 var parameterVar = Expression.Variable(parameter.ParameterType, parameter.Name); 75 var parameterType = TypeHelper.GetUnderlyingType(parameter.ParameterType); 76 switcher = new DataReaderGetMethodSwitcher(parameterType, readIndexVar, readerVar); 77 switcher.Process(); 78 var rightExp = (Expression)switcher.Result; 79 if (TypeHelper.IsNullableType(parameter.ParameterType)) 80 { 81 rightExp = Expression.Convert(rightExp, parameter.ParameterType); 82 } 83 var isNullExp = Expression.Call(readerExp, ReflectorConsts.IsDBNullfIDataReader, readIndexVar); 84 var ifExp = Expression.IfThenElse(isNullExp, Expression.Assign(parameterVar, Expression.Default(parameter.ParameterType)), Expression.Assign(parameterVar, rightExp)); 85 var exps = new List<Expression>(); 86 setEntityExpressions.Add( 87 Expression.Assign( 88 readIndexVar, 89 Expression.ArrayIndex(indexArrVar, Expression.Constant(i)) 90 ) 91 ); 92 setEntityExpressions.Add(ifExp); 93 expressionParams.Add(parameterVar); 94 } 95 setEntityExpressions.Add(Expression.Assign(objVar, Expression.New(constructor, expressionParams))); 96 paramterExpressions.AddRange(expressionParams); 97 paramterExpressions.Add(readerVar); 98 paramterExpressions.Add(listVar); 99 } 100 else 101 { 102 var newExp = Expression.New(type); 103 setEntityExpressions.Add(Expression.Assign(objVar, newExp)); 104 for (int i = 0; i < fieldCount; i++) 105 { 106 var propertyName = reader.GetName(i); 107 var property = properties.Get(propertyName); 108 if (property == null) 109 { 110 continue; 111 } 112 var propertyAssignExpressions = new List<Expression>(); 113 var propertyExp = Expression.Property(objVar, property); 114 var propertyType = TypeHelper.GetUnderlyingType(property.PropertyType); 115 Expression rightExp = null; 116 switcher = new DataReaderGetMethodSwitcher(propertyType, readIndexVar, readerVar); 117 switcher.Process(); 118 rightExp = (Expression)switcher.Result; 119 if (TypeHelper.IsNullableType(property.PropertyType)) 120 { 121 rightExp = Expression.Convert(rightExp, property.PropertyType); 122 } 123 setEntityExpressions.Add( 124 Expression.Assign( 125 readIndexVar, 126 Expression.ArrayIndex(indexArrVar, Expression.Constant(i)) 127 ) 128 ); 129 var ifExp = Expression.IfThen( 130 Expression.Not( 131 Expression.Call(readerExp, ReflectorConsts.IsDBNullfIDataReader, readIndexVar) 132 ), 133 Expression.Assign(propertyExp, rightExp) 134 ); 135 setEntityExpressions.Add(ifExp); 136 } 137 paramterExpressions.Add(listVar); 138 paramterExpressions.Add(readerVar); 139 } 140 paramterExpressions.Add(indexVar); 141 paramterExpressions.Add(propertyNameArr); 142 paramterExpressions.Add(fieldCountVar); 143 paramterExpressions.Add(indexArrVar); 144 paramterExpressions.Add(readIndexVar); 145 //expressions.Add(Expression.Call( 146 // null, 147 // typeof(MessageBox).GetMethod("Show", new Type[] { ReflectorConsts.StringType }), 148 // Expression.Call( 149 // null, 150 // ReflectorConsts.ConvertToStringMethod, 151 // Expression.Convert( 152 // Expression.ArrayIndex(indexArrVar, Expression.Constant(1)), 153 // ReflectorConsts.ObjectType) 154 // ))); 155 setEntityExpressions.Add(Expression.Call(listVar, listType.GetMethods().FirstOrDefault(x => x.Name == "Add"), objVar)); 156 expressions.Add( 157 Expression.Loop( 158 Expression.Block( 159 Expression.IfThenElse( 160 Expression.Call(readerVar, ReflectorConsts.ReadOfIDataReader), 161 Expression.Block(new[] { objVar }, setEntityExpressions), 162 Expression.Break(labelTarget, Expression.Default(type)) 163 ) 164 ), 165 labelTarget 166 )); 167 expressions.Add(listVar); 168 body = Expression.Block( 169 paramterExpressions, 170 expressions 171 ); 172 func = Expression.Lambda<Func<IDataReader, IList>>(body, readerExp).Compile(); 173 _dataReader2ListCahce.Add(type, func); 174 } 175 } 176 } 177 return func; 178 } View Code

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved