Performance: Using LCG to copy property values of two objects

Today I gave last performance boost to my property values copying mechanism. I would like to thank my readers Ron and David to remind me Lightweight Code Generation (LCG) and pointing me out aussie bloke blog entry Generic copy object using Lightweight Code Generation. In this posting I will show you last performance boost and put down a summary about my experiment this far.

To get better idea about what I have done this far please also read first two posts in this series.

Copying matching properties – Lightweight Code Generation (LCG)

The last performance boost was achieved by using LCG. I created static dictionary to cache generic delegates that invoke dynamically generated methods that perform actual copying. These methods are generated using Intermediate Language (IL) opcodes. Here is the code.

delegate void CopyPublicPropertiesDelegate<T,TU> 
        (T source, TU target);
 

static Dictionary<string, object
> _del =
   
new Dictionary<string, object
>();
 

static void
GenerateCopyDelegate<T, TU>()
{
   
var className = GetClassName(typeof(T), typeof
(TU));
   
var args = new[] {typeof(T), typeof
(TU)};
   
var mod = typeof
(Program).Module;
 
   
var dm = new DynamicMethod(className, null
, args, mod);
   
var
il = dm.GetILGenerator();          
   
var
maps = _maps[className];
 
   
foreach (var map in
maps)
    {
        il.Emit(
OpCodes
.Ldarg_1);
        il.Emit(
OpCodes
.Ldarg_0);
        il.EmitCall(
OpCodes
.Callvirt,
                    map.SourceProperty.GetGetMethod(),
null
);
        il.EmitCall(
OpCodes
.Callvirt,
                    map.TargetProperty.GetSetMethod(),
null
);
    }
    il.Emit(
OpCodes
.Ret);
 
   
var del = (CopyPublicPropertiesDelegate<T,TU>)dm.CreateDelegate(typeof(CopyPublicPropertiesDelegate
<T,TU>));
    _del.Add(className, del);
}
 

static void
CopyUsingLcg<T, TU>(T source, TU target)
{
   
var
sourceType = source.GetType();
   
var
targetType = target.GetType();
   
var
className = GetClassName(sourceType, targetType);
 
   
var del = (CopyPublicPropertiesDelegate<T, TU>)
              _del[className];
    del.Invoke(source, target);
}

The best result in my last posting was 0,0055 milliseconds (it was measured as average over 100.000 copy operations). LCG gives even better result: 0,0018 milliseconds! It is 3 times better than previous optimization.

Summary

Well… after four tries my results are as follows. Third column shows how many times performance grew compared to previous optimization. Fourth column show how much performance grew compared to first and unoptimized version.

Properties copying performance chart

Why I compare results to first one that is completely dumb and non-optimized version? Well… don’t forget that out there are people in hurry (by example, soldiers in death march projects). And there are also beginners who are not aware of these more complex optimization methods. These two cases are major dangers where performance problems are naturally coded. You can see here how much you can do for performance when using more complex optimization methods. I think performance raise ~22.4 times is not unnoticeable small thing.

Conclusion

Can we go any further from here? Yes, we can. The code you have seen so far sits in static class that is compiled to command line application. As a next thing I want to make this code reusable for different applications. I have some ideas but I have to think what is best solution in my scenario. But you will hear about this topic soon. :)

Gunnar Peipman

Gunnar Peipman is ASP.NET, Azure and SharePoint fan, Estonian Microsoft user group leader, blogger, conference speaker, teacher, and tech maniac. Since 2008 he is Microsoft MVP specialized on ASP.NET.

    6 thoughts on “Performance: Using LCG to copy property values of two objects

    Leave a Reply

    Your email address will not be published. Required fields are marked *