c# - Don't the expression need to be faster for getting a property value than the reflection? -
i know using look faster getting property value using reflection, convert list datatable, have used both of them,
the reflection elapsed time : 36 ms
the look elapsed time : 2350 ms
i wonder doing wrong there?
i have tried below code :
public class foo { public long intcode { get; set; } public string name { get; set; } public string surname { get; set; } public int age { get; set; } } class programme { static void main(string[] args) { var r = new random(); var foos = new list<foo>(); var sw = new stopwatch(); sw.start(); (int = 0; < 10000; i++) { foos.add(new foo { intcode = r.next(), name = guid.newguid().tostring(), surname = guid.newguid().tostring(), age = r.next() }); } sw.stop(); console.writeline("elapsed time creating : {0}", sw.elapsedmilliseconds); sw.restart(); convertwithreflection(foos, "intcode", "name", "age"); sw.stop(); console.writeline("elapsed time converting : {0}", sw.elapsedmilliseconds); sw.restart(); convertwithexpression(foos, "intcode", "name", "age"); sw.stop(); console.writeline("elapsed time converting : {0}", sw.elapsedmilliseconds); console.readline(); } public static object getvaluegetter<t>(object item,string propertyname) { var arg = expression.parameter(item.gettype(), "x"); look expr = expression.property(arg, propertyname); var unaryexpression = expression.convert(expr, typeof(object)); var propertyresolver = expression.lambda<func<t, object>>(unaryexpression, arg).compile(); var value = propertyresolver((t)item); homecoming value; } public static void convertwithreflection<t>(ienumerable<t> list, params string[] columnnames) { var t = list.tolist(); if (!t.any()) return; var datatable = new datatable(); datatable.columns.add("intcode"); datatable.columns.add("name"); datatable.columns.add("surname"); datatable.columns.add("age"); foreach (var item in t) { var dr = datatable.newrow(); (int = 0; < datatable.columns.count; i++) { var el = columnnames.elementatordefault(i); if (el == null) { dr[i] = dbnull.value; } else { var property = item.gettype().getproperty(el); dr[i] = property.getvalue(item, null); } } datatable.rows.add(dr); } } public static void convertwithexpression<t>(ienumerable<t> list, params string[] columnnames) { var t = list.tolist(); if (!t.any()) return; var datatable = new datatable(); datatable.columns.add("intcode"); datatable.columns.add("name"); datatable.columns.add("surname"); datatable.columns.add("age"); foreach (var item in t) { var dr = datatable.newrow(); (var = 0; < datatable.columns.count; i++) { var el = columnnames.elementatordefault(i); if (el == null) { dr[i] = dbnull.value; } else { dr[i] = getvaluegetter<t>(item, el); } } datatable.rows.add(dr); } } }
you not comparing apples apples: look code constructs , compiles look on each iteration, producing fair amount of throw-away activity @ each iteration. reflection code, on other hand, uses optimizations designers of clr have set system, performing necessary operations.
essentially, comparing preparation time + working time expressions vs. working time reflection. not intended way of using expressions in situations when action repeated 10,000 times: expected prepare , compile lambdas upfront, store them in cache of sort, , retrieve them needed on each iteration. implementing sort of caching out comparison:
public static object getvaluegetter<t>(object item, string propertyname, idictionary<string,func<t,object>> cache) { func<t, object> propertyresolver; if (!cache.trygetvalue(propertyname, out propertyresolver)) { var arg = expression.parameter(item.gettype(), "x"); look expr = expression.property(arg, propertyname); var unaryexpression = expression.convert(expr, typeof (object)); propertyresolver = expression.lambda<func<t, object>>(unaryexpression, arg).compile(); cache.add(propertyname, propertyresolver); } homecoming propertyresolver((t)item); }
call looks this:
var cache = new dictionary<string,func<t,object>>(); foreach (var item in t) { var dr = datatable.newrow(); (var = 0; < datatable.columns.count; i++) { var el = columnnames.elementatordefault(i); if (el == null) { dr[i] = dbnull.value; } else { dr[i] = getvaluegetter<t>(item, el, cache); } } datatable.rows.add(dr); }
now costs of preparation spread across 10,000 calls, reflections becomes slower of 3 methods:
elapsed time creating : 29 elapsed time converting : 84 <-- reflection elapsed time converting : 53 <-- expressions
c# performance reflection expression
No comments:
Post a Comment