Skip to content

Instantly share code, notes, and snippets.

@jorupp
Created January 10, 2015 00:50
Show Gist options
  • Save jorupp/b09879f35858e9692461 to your computer and use it in GitHub Desktop.
Save jorupp/b09879f35858e9692461 to your computer and use it in GitHub Desktop.
Expression-to-avoid-reflection example
/**
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