我有一个方法,它通过 7,753+ 个对象使用循环并获取每个对象的每个属性的值.每个对象都有 14 个属性.
I have a method that uses loops through 7,753+ objects and Gets the value of each property for each object. Each object has 14 properties.
private void InitializeData(IList objects, PropertyInfo[] props, List<DPV> dataPs, List<Dictionary<string, object>> tod) { foreach (var item in objects) { var kvp = new Dictionary<string, object>(); foreach (var p in props) { var dataPs = dataPs.FirstOrDefault(x => x.Name == p.Name); object returnData; if (dataPoint != null) { int maxLength = (dataP.MaxLength == null) ? 0 : (int) dataP.MaxLength; returnData = p.GetValue(item, null); if (!string.IsNullOrEmpty(dataP.FormatString) && !string.IsNullOrEmpty(returnData.ToString())) { returnData = FormatDataForDisplay(returnData, dataP, maxLength, "", 8); } } else { returnData = p.GetValue(item, null); } kvp.Add(p.Name, returnData); } tod.Add(kvp); } }我相信 GetValue 是这个方法中花费大部分时间的方法,该方法花费了大约 900ms 来运行,但是 GetValue被调用 800,000+ 次大约需要 750 毫秒(总共,不是每次调用).
I believe GetValue is what takes the majority of the time in this method, The method took around 900ms to run, but GetValue which is called 800,000+ times takes around 750ms (total, not per-call).
public List<Dictionary<string, object>> GetColumnOptions<T>(List<T> list) { var tod= new List<Dictionary<string, object>>(); var objects = (IList)list[0]; Type objType = objects[0].GetType(); var props = objType.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance); var dPs= GetDPs(); //Initialize aaData //I don't believe this is correct InitializeData2<T>(new List<T> { (T) objects}, props, dPs, tod); return tod; } 推荐答案对于您的值类,您可以创建直接的 setter 和 getter lambda.性能几乎与直接访问属性一样快.
For your value class you can create direct setter and getter lambda. The performance is nearly as fast as directly accessing the properies.
从 PropertyInfo 获取 Setter
var propertyInfo = typeof(MyType).GetProperty("MyPropertValue"); var propertySetter = FastInvoke.BuildUntypedSetter<T>(propertyInfo)); var fieldInfo = typeof(MyType).GetField("MyFieldValue"); var fieldSetter = FastInvoke.BuildUntypedSetter<T>(fieldInfo));循环使用
var myTarget = new MyType(); setter(myTarget, aNewValue)检索快速 Setter 和 Getter 的助手
public static class FastInvoke { public static Func<T, object> BuildUntypedGetter<T>(MemberInfo memberInfo) { var targetType = memberInfo.DeclaringType; var exInstance = Expression.Parameter(targetType, "t"); var exMemberAccess = Expression.MakeMemberAccess(exInstance, memberInfo); // t.PropertyName var exConvertToObject = Expression.Convert(exMemberAccess, typeof(object)); // Convert(t.PropertyName, typeof(object)) var lambda = Expression.Lambda<Func<T, object>>(exConvertToObject, exInstance); var action = lambda.Compile(); return action; } public static Action<T, object> BuildUntypedSetter<T>(MemberInfo memberInfo) { var targetType = memberInfo.DeclaringType; var exInstance = Expression.Parameter(targetType, "t"); var exMemberAccess = Expression.MakeMemberAccess(exInstance, memberInfo); // t.PropertValue(Convert(p)) var exValue = Expression.Parameter(typeof(object), "p"); var exConvertedValue = Expression.Convert(exValue, GetUnderlyingType(memberInfo)); var exBody = Expression.Assign(exMemberAccess, exConvertedValue); var lambda = Expression.Lambda<Action<T, object>>(exBody, exInstance, exValue); var action = lambda.Compile(); return action; } private static Type GetUnderlyingType(this MemberInfo member) { switch (member.MemberType) { case MemberTypes.Event: return ((EventInfo)member).EventHandlerType; case MemberTypes.Field: return ((FieldInfo)member).FieldType; case MemberTypes.Method: return ((MethodInfo)member).ReturnType; case MemberTypes.Property: return ((PropertyInfo)member).PropertyType; default: throw new ArgumentException ( "Input MemberInfo must be if type EventInfo, FieldInfo, MethodInfo, or PropertyInfo" ); } } }============ 添加了性能分析 ====================
============= Performance Analysis Added ===================
5 个 Mio 对象,20 个属性
- 3.4s 直接访问属性
- 130.0s 通过 PropertyInfo.SetValue
- 4.0s 通过 TypedSetter(文章中显示的代码)
- 9.8s 通过 UnTypedSetter(上面的代码)
- 3.4s direct Property access
- 130.0s via PropertyInfo.SetValue
- 4.0s via TypedSetter (code shown in article)
- 9.8s via UnTypedSetter (code above)
诀窍是为每个类生成一次 property-setter 和 -getter,然后重用它们.
The trick is to generate the property-setter and -getter once for each class an reuse them.
// Create an fill objects fast from DataReader // flurfunk.sdx-ag.de/2012/05/c-performance-bei-der-befullungmapping.html static List<T> CreateObjectFromReader<T>(IDataReader reader) where T : new() { // Prepare List<string> fieldNames = GetFieldNames(reader); List<Action<T, object>> setterList = new List<Action<T, object>>(); // Create Property-Setter and store it in an array foreach (var field in fieldNames) { var propertyInfo = typeof(T).GetProperty(field); setterList.Add(FastInvoke.BuildUntypedSetter<T>(propertyInfo)); } Action<T, object>[] setterArray = setterList.ToArray(); // generate and fill objects while (reader.Read()) { T xclass = new T(); int fieldNumber = 0; for (int i = 0; i< setterArray.Length; i++) { // call setter setterArray[i](xclass, reader.GetValue(i)); fieldNumber++; } result.Add(xclass); } }我的原始文章(德语文本和旧代码)是 web.archive/web/20141020092917/flurfunk.sdx-ag.de/2012/05/c-性能-bei-der-befullungmapping.html
My original article (german text and older code) was web.archive/web/20141020092917/flurfunk.sdx-ag.de/2012/05/c-performance-bei-der-befullungmapping.html
更多推荐
是否可以加快这种方法的速度?
发布评论