This project has moved and is read-only. For the latest updates, please go here.

Benchmarks

We've coded a benchmark application to demonstrate compare the performance Fasterflect against direct member invocation and standard .NET Reflection invocations (and the usage of 'dynamic' in .NET 4.0). The benchmark application is executed under both .NET 3.5 and .NET 4.0 RC (click on the link to see the result). There are a couple of interesting observations when looking at those benchmark results.
  • Under .NET 3.5, the standard API and delegate API of Fasterflect performs 6-10 times faster and 200-300 times faster respectively than standard .NET Reflection calls
  • Microsoft has obviously done a lot of work to improve Reflection performance in .NET 4.0 so the gain of Fasterflect isn't that impressive under .NET 4.0. But still, the standard API is still faster (except for the case of instance field access) and delegate API significantly faster.
  • .NET 4.0's 'dynamic' performs quite decently (faster than Fasterfect's standard API and only slower than Fasterflect's delegate API). This far from meaning that 'dynamic' is going to make the standard API of Fasterflect obsolete though because 'dynamic' out-of-the-box can only do a small subset of what Fasterflect can do.

Note that the performance gain is only available for Accessing functionality of Fasterflect only. The Querying functionality (i.e. metadata lookup) is is just wrapper of the .NET Reflection API, so it does indeed add overhead to the standard .NET Reflection calls.

How the Benchmark is Done

The utility methods that perform the measurement are defined as follows:
private static void Execute(string name, Dictionary<string, Action> initMap, Dictionary<string, Action> actionMap)
{
	Console.WriteLine("------------- {0} ------------- ", name);

	Console.WriteLine("*** Initialization");
	Measure(Watch, initMap, 1);
	Console.WriteLine();

	foreach (int iterationCount in Iterations)
	{
		Console.WriteLine("*** Executing for {0} iterations", iterationCount);
		Measure(Watch, actionMap, iterationCount);
		Console.WriteLine();
	}
	Console.WriteLine();
}

private static void Measure(Stopwatch watch, Dictionary<string, Action> actionMap, int iterationCount)
{
	foreach (var entry in actionMap)
	{
		watch.Start();
		for (int i = 0; i < iterationCount; i++)
			entry.Value();
		watch.Stop();
		Console.WriteLine("{0,-35} {1,6} ms", entry.Key + ":", watch.ElapsedMilliseconds);
		watch.Reset();
	}
}

Specific benchmark code can then be built upon the above utility methods. For example the benchmark code for the object construction is shown below. You can find the rest of the source code in FasterflectBenchmark project.
private static void RunConstructorBenchmark()
{
    ConstructorInfo ctorInfo = null;
    ConstructorInvoker invoker = null;

    var initMap = new Dictionary<string, Action>
                  {
                      {
                          "Init info", () =>
                                       {
                                           ctorInfo = typeof(Person).GetConstructor(
                                               BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[0],
                                               null );
                                       }
                          },
                      { "Init ctorInvoker", () => { invoker = typeof(Person).DelegateForCreateInstance(); } },
                  };
    var actionMap = new Dictionary<string, Action>
                    {
                        { "Direct ctor", () => new Person() },
                        { "Reflection ctor", () => ctorInfo.Invoke( NoArgArray ) },
                        { "Fasterflect ctor", () => typeof(Person).CreateInstance() },
                        { "Fasterflect cached ctor", () => invoker( NoArgArray ) },
                    };
    Execute( "Benchmark for Object Construction", initMap, actionMap );
}


Last edited Mar 7, 2010 at 11:44 AM by buunguyen, version 9

Comments

misaxi Apr 22, 2011 at 7:50 AM 
Could you please indicate how fast is it in .NET 4.0 by data like you describes for that in .NET 3.5 under the same benchmarking environment? I am really curious about it.