Thursday, January 11, 2007

Improving FileHelpers Performance with Reflection Emit

I´m in the works for the version 2.0 of the library and one of the milestones is to improve a bit the performance (mostly the use of reflection and string handling)

Now I´m trying to use the cool DynamicMethods of .NET 2.0 and I´m surprised how easy and fast them are !!

I just finish to implement the setters via a Dynamic Method using the CreateDelegate and I get a 25% of improved performance over the past versions !!!! (in files with more than 500 or 1000 records)

Here is the code that I´m using:

For example in the FieldBase I was using the FieldInfo.SetValue but now I create a new method at run time

(Suppose that the RecordClass is SampleType and the field Field1 of DateTime)

static void SetField1(object record, object val)

{

((SampleType)record).Field1 = (DateTime)val;

}

I need so a Delegate for these methods calls (all private to the FieldBase class)

delegate void SetValueDelegate(object record, object value);

SetValueDelegate mSetDelegate;

finally playing a bit with Reflector we need to add to the constructor we need these lines:

protected FieldBase(FieldInfo fi)

{

DynamicMethod dm = new DynamicMethod("__SetFH__" + fi.Name, typeof(void),

new Type[] { typeof(object), typeof(object) }, fi.DeclaringType, true);

ILGenerator il = dm.GetILGenerator();

il.Emit(OpCodes.Ldarg_0);

il.Emit(OpCodes.Castclass, fi.DeclaringType);

il.Emit(OpCodes.Ldarg_1);

if (fi.FieldType.IsValueType)

il.Emit(OpCodes.Unbox_Any, fi.FieldType);

else

il.Emit(OpCodes.Castclass, fi.FieldType);

il.Emit(OpCodes.Stfld, fi);

il.Emit(OpCodes.Ret);

mSetDelegate = (SetValueDelegate)dm.CreateDelegate(typeof(SetValueDelegate));

And at last instead of using the slow:

mFieldInfo.SetValue(record, val);

We use :

mSetDelegate(record, val);

I will post the benchmarks when I finish the tweaks.

See ya