Created
January 10, 2015 00:50
-
-
Save jorupp/b09879f35858e9692461 to your computer and use it in GitHub Desktop.
Expression-to-avoid-reflection example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
Simple example to show off a way of using expressions to avoid doing reflection for each item to process. | |
Example results: | |
TestSimple with 300000 items: 00:00:00.0003998 setup, 00:00:02.3790693 processing | |
TestCache1 with 300000 items: 00:00:00.0005534 setup, 00:00:02.4511439 processing | |
TestCache2 with 300000 items: 00:00:00.0048780 setup, 00:00:00.1950776 processing | |
**/ | |
public class MyClass { | |
public int Prop1 { get; set; } | |
public int Prop2 { get; set; } | |
public int Prop3 { get; set; } | |
public int Prop4 { get; set; } | |
public int Prop5 { get; set; } | |
public int Prop6 { get; set; } | |
public int Prop7 { get; set; } | |
public int Prop8 { get; set; } | |
public int Prop9 { get; set; } | |
public int Prop10 { get; set; } | |
} | |
void TestSimple<T>(Action setupComplete, int count) where T: new() { | |
setupComplete(); | |
for(var i=0; i<count; i++) { | |
var type = typeof(T); | |
var t = new T(); | |
foreach(var pi in type.GetProperties()) { | |
pi.SetValue(t, 3); | |
pi.GetValue(t); | |
} | |
} | |
} | |
void TestCache1<T>(Action setupComplete, int count) where T: new() { | |
var type = typeof(T); | |
var props = type.GetProperties(); | |
setupComplete(); | |
for(var i=0; i<count; i++) { | |
var t = new T(); | |
foreach(var pi in props) { | |
pi.SetValue(t, 3); | |
pi.GetValue(t); | |
} | |
} | |
} | |
void TestCache2<T>(Action setupComplete, int count) where T: new() { | |
var type = typeof(T); | |
var props = type.GetProperties().Select (p => { | |
var tParam = Expression.Parameter(type, "t"); | |
var valueParam = Expression.Parameter(typeof(int), "value"); | |
var setBody = Expression.Assign(Expression.Property(tParam, p), valueParam); | |
var getBody = Expression.Property(tParam, p); | |
return new { | |
set = LambdaExpression.Lambda<Action<T, int>>(setBody, tParam, valueParam).Compile(), | |
get = LambdaExpression.Lambda<Func<T, int>>(getBody, tParam).Compile(), | |
}; | |
}).ToArray(); | |
setupComplete(); | |
for(var i=0; i<count; i++) { | |
var t = new T(); | |
foreach(var pi in props) { | |
pi.set(t, 3); | |
pi.get(t); | |
} | |
} | |
} | |
void DoTest(int count, Action<Action, int> testMethod, string testName) { | |
var sw = Stopwatch.StartNew(); | |
TimeSpan setupComplete = TimeSpan.Zero; | |
testMethod(() => { | |
setupComplete = sw.Elapsed; | |
}, count); | |
var elapsed = sw.Elapsed; | |
Console.WriteLine("{0} with {1} items: {2} setup, {3} processing", testName, count, setupComplete, elapsed - setupComplete); | |
} | |
void Main() | |
{ | |
var count = 300000; | |
DoTest(count, (a,c) => TestSimple<MyClass>(a,c), "TestSimple"); | |
DoTest(count, (a,c) => TestCache1<MyClass>(a,c), "TestCache1"); | |
DoTest(count, (a,c) => TestCache2<MyClass>(a,c), "TestCache2"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment