2012/08/09

Dynamic methods for accessing fields

A few weeks ago I was facing some performance issues with a DeepCopy class I wrote. The goal of this class is to provide a faster way for deep-copying an object graph rather than serializing and deserializing with BinaryFormatter. The performance analysis of my code showed that getting or setting a field via FieldInfo.GetValue and FieldInfo.SetValue was very slow. So I searched for a possibility to access fields in a faster way. I found some interesting things, but not exactly what i was looking for.

The Idea

I got the basic idea from this page:

Jachman Wordpress - 2000% faster using dynamic method calls/

It describes a way of accessing properties with dynamic methods. The difference between properties and fields is that for accessing a property you have to call it's get- or set-method, when accessing a field the C# compiler will use special IL instructions to get or set the value.

Analyse the IL code (Getter)

The fastest way to access a field is to directly access it:
public class FieldAccessorsExample
{
    public string _field1;
    public int _field2;
}

// access
var instance = new SomeClass();
var value = instance._someField;

To get high performance getters and setters, we should have some methods which will imitate the direct access. I thought of something like this:

public static object Getter(object source)
{
    return ((FieldAccessorsExample)source)._field1;
}
After compiling the code above, we can view the IL code with ILDisassembler from Visual Studio. To understand the IL code, I found the documentation of the OpCodes class very helpful.
.method public hidebysig static object  Getter(object source) cil managed
{
  // Code size       12 (0xc)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  castclass  FieldSetterGetter.FieldAccessorsExample
  IL_0006:  ldfld      string FieldSetterGetter.FieldAccessorsExample::_field1
  IL_000b:  ret
} // end of method FieldAccessorsExample::Getter

For accessing value types the method looks a little bit different.

.method private hidebysig static object  ValueTypeGetter(object source) cil managed
{
  // Code size       17 (0x11)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  castclass  FieldSetterGetter.FieldAccessorsExample
  IL_0006:  ldfld      int32 FieldSetterGetter.FieldAccessorsExample::_field2
  IL_000b:  box        [mscorlib]System.Int32
  IL_0010:  ret
} // end of method FieldAccessorsExample::ValueTypeGetter

With this as the basic template I created the method which will generate our get-function.
public static Func<object, object> GetGetter(FieldInfo fieldInfo)
{
    // create a method without a name, object as result type and one parameter of type object
    // the last parameter is very import for accessing private fields
    var method = new DynamicMethod(string.Empty, typeof(object), new []{ typeof(object) }, fieldInfo.Module, true);
    var il = method.GetILGenerator();

    il.Emit(OpCodes.Ldarg_0); // load the first argument onto the stack (source of type object)
    il.Emit(OpCodes.Castclass, fieldInfo.DeclaringType); // cast the parameter of type object to the type containing the field
    il.Emit(OpCodes.Ldfld, fieldInfo); // store the value of the given field on the stack. The casted version of source is used as instance
    
    if(fieldInfo.FieldType.IsValueType)
        il.Emit(OpCodes.Box, fieldInfo.FieldType); // box the value type, so you will have an object on the stack

    il.Emit(OpCodes.Ret); // return the value on the stack

    return (Func<object, object>)method.CreateDelegate(typeof(Func<object, object>));
}

Analyse the IL code (Setter)

Now we will just do the same for the set-function. First a simple function which could set the value on a given instance.
public void Setter(object target, object value)
{
    ((FieldAccessorsExample)target)._field1 = (string)value;
}

The IL code generated by the compiler is:

.method public hidebysig static void  Setter(object target,
                                             object 'value') cil managed
{
  // Code size       18 (0x12)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  castclass  FieldSetterGetter.FieldAccessorsExample
  IL_0006:  ldarg.1
  IL_0007:  castclass  [mscorlib]System.String
  IL_000c:  stfld      string FieldSetterGetter.FieldAccessorsExample::_field1
  IL_0011:  ret
} // end of method FieldAccessorsExample::Setter
Or the following for value types:
.method public hidebysig static void  ValueTypeSetter(object target,
                                                      object 'value') cil managed
{
  // Code size       18 (0x12)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  castclass  FieldSetterGetter.FieldAccessorsExample
  IL_0006:  ldarg.1
  IL_0007:  unbox.any  [mscorlib]System.Int32
  IL_000c:  stfld      int32 FieldSetterGetter.FieldAccessorsExample::_field2
  IL_0011:  ret
} // end of method FieldAccessorsExample::ValueTypeSetter

From this we can create the function, which will return our setter function:
public static Action<object, object> GetSetter(FieldInfo fieldInfo)
{
    var method = new DynamicMethod(string.Empty, null, new[] { typeof(object), typeof(object) }, fieldInfo.Module, true);
    var il = method.GetILGenerator();

    il.Emit(OpCodes.Ldarg_0); // load the first argument onto the stack (source of type object)
    il.Emit(OpCodes.Castclass, fieldInfo.DeclaringType); // cast the parameter of type object to the type containing the field
    il.Emit(OpCodes.Ldarg_1); // push the second argument onto the stack (this is the value)

    if (fieldInfo.FieldType.IsValueType)
        il.Emit(OpCodes.Unbox_Any, fieldInfo.FieldType); // unbox the value parameter to the value-type
    else
        il.Emit(OpCodes.Castclass, fieldInfo.FieldType); // cast the value on the stack to the field type

    il.Emit(OpCodes.Stfld, fieldInfo); // store the value on stack in the field
    il.Emit(OpCodes.Ret); // return

    return (Action<object, object>)method.CreateDelegate(typeof(Action<object, object>));
}

Usage

If you put the two functions above in a factory class, the usage could look like this:

var getter = FieldAccessorFactory.GetGetter(fieldInfo);
var setter = FieldAccessorFactory.GetSetter(fieldInfo);
 
var oldValue = getter(instance);
setter(instance, "newvalue");
Some helpful informations can also be found by searching with google for "open delegates" in C#.
This page explains the basics.

Performance

10,000,000 Reads

With Reflection: 3.77 sec
With DynamicMethod: 0.17 sec
Factor: 21.9


10,000,000 Writes

With Reflection: 5,14 sec
With DynamicMethod: 0.25
Factor: 20.7

If you have any suggestions or questions, comment.


2012/08/08

Setup blogger with syntax highlighting

Before I will post the first source code I was looking how to setup syntax highlighting with blogger.com. For anyone who would like to know:

http://mlawire.blogspot.de/2009/07/blogger-syntax-highlighting.html

Very simple :)

EDIT 2012/08/14:
It wasn't as simple as I thought. After digging arount a little i found how to do it properly.
This links helped me out:

http://derkan.blogspot.de/2011/11/adding-syntaxhighlighter-to-blogger.html

Basically you have to copy the content of the css files you will use under Templates->Customize->Advanced->Add Css

I used the files

https://github.com/alexgorbatchev/SyntaxHighlighter/blob/master/styles/shCore.css
https://github.com/alexgorbatchev/SyntaxHighlighter/blob/master/styles/shCoreDefault.css

After clicking Apply to Blog you can add the code from the derkan blog to your post. I modified the code for my needs like this:

<div style="display:none">
<pre class="brush:js"></pre>
<pre class="brush:csharp"></pre>
</div>

<script type="text/javascript">
 function loadScript(url, callback){
  var script = document.createElement("script")
  script.type = "text/javascript";
  if (script.readyState){  //IE
   script.onreadystatechange = function(){
    if (script.readyState == "loaded" ||
      script.readyState == "complete"){
     script.onreadystatechange = null;
     callback();
    }
   };
  } else {  //Others
   script.onload = function(){
    callback();
   };
  }
  script.src = url;
  document.getElementsByTagName("head")[0].appendChild(script);
 }
 loadScript("http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js", 
  function(){
   loadScript("http://alexgorbatchev.com/pub/sh/current/scripts/shAutoloader.js", 
    function(){
     SyntaxHighlighter.config.bloggerMode = true;
     SyntaxHighlighter.autoloader(
             'c# c-sharp csharp http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCSharp.js',
'js jscript javascript http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js'
     );     
     SyntaxHighlighter.all();
    }  
   );
  }
 );
</script>

The invisible div forces the load of all scripts, you wan't to use. Without this div it could happen, that you would get an error saying: brush XYZ not found.

Infos about the autoloader script you can find here.



Starting a new blog

Today I started this new blog "Sharp Analytics". The first part was to find a name for this blog. It will be mainly about IT and programming with C# and WPF. Sharp Analytics was a name which stresses some part of working with PCs. Especially in programming I realize every day that it's better to do a smart analysis before you start working ;).

I am looking forward to write the next post. 'til then...