Archive

Archive for the ‘Reflection’ Category

Activator.CreateInstance Optimization

July 12, 2013 Leave a comment

Reflection is a powerful feature of the .NET platform. Whether it’s for querying a type’s properties or creating instances of objects dynamically, reflection can help in many architectural designs. But as Uncle Ben said:

With great power comes great responsibility

In fact, as a programmer you have to be careful when you use reflection because it comes with a cost. In most cases, that cost is minimal and will not impact the performance or scalability of your application. But in some cases, that cost can truly bring your application to its knees. In this article I’ll analyze the performance of the Activator class and provide optimized implementations for most of its methods.

It’s important to note that the performance of the Activator class has been improved in .NET 4 compared to .NET 3.5.

image

There are many flavors of optimized CreateInstance implementations out there but I find most of them not really intuitive to use. There are generally 2 approaches to this problem: Compiling lambda expressions or generating dynamic methods in IL. Both approaches require code generation at runtime and therefore cannot be used without a JIT compiler (mono under iOS for example). The IL approach executes slightly faster than compiled lambdas so that’s what I’ll be using.

As Jon Skeet points out in his blog, invocation through reflection is quite slow and delegates provide a faster way of invoking methods. So my strategy to improve the performance of CreateInstance is to create and cache a delegate to the constructor of a given type.

Activator.CreateInstance<T>()

To optimize the statically typed version of CreateInstance, we will use a static generic class which will hold the delegate to the constructor. So instead of calling:

Activator.CreateInstance<T>()

We will use:

Activator<T>.CreateInstance()

Simple and intuitive. Here’s the implementation:

public static class Activator<T> where T : class, new()
{
    public static Func<T> CreateInstance { get; private set; }

    static Activator()
    {
        CreateInstance = typeof(T).GetConstructorDelegate<T>();
    }
}

The magic happens in the extension method Type.GetConstructorDelegate<T> which we will cover later on. This statically typed Activator also works for constructors with parameters as long as you know the exact parameter types of the constructor signature you are targeting:

public static class Activator<T, TArg1> where T : class
{
    public static Func<TArg1, T> CreateInstance { get; private set; }

    static Activator()
    {
        CreateInstance = (Func<TArg1, T>)typeof(T).GetConstructorDelegate(typeof(Func<TArg1, T>));
    }
}

Which can be called like this:

Activator<T, TArg1>.CreateInstance(arg1)

You can create more versions of the Activator class depending on the number of arguments you want to support: Activator<T, TArg1, TArg2>, Activator<T, TArg1, TArg2, TArg3>, etc.

Activator.CreateInstance(Type)

To optimize this method we will create an extension method to the Type class. So instead of calling:

Activator.CreateInstance(type)

We will use:

type.CreateInstance()

Not as intuitive but this way we won’t have a namespace clash with multiple Activator classes. Another way would be to name the static classes FastActivator, FastActivator<T>, etc. and keep all the methods in one place. I’ll leave that up to you. Here’s how this extension method is implemented:

public static class TypeExtensions
{
    private static readonly ConcurrentDictionary<Type, Func<object>> _constructors = new ConcurrentDictionary<Type, Func<object>>();

    public static object CreateInstance(this Type type)
    {
        Func<object> constructor;
        if (!_constructors.TryGetValue(type, out constructor))
        {
            constructor = type.GetConstructorDelegate();
            _constructors.TryAdd(type, constructor);
        }
        return constructor();
    }
}

We can also create signatures with statically typed arguments:

public static object CreateInstance<TArg1>(this Type type, TArg1 arg1)
{
    return PrivateActivator<TArg1>.CreateInstance(type, arg1);
}

Which can be used like this:

type.CreateInstance(arg1)

A static method with its associated PrivateActivator class will need to be created to support more arguments. The implementation of the PrivateActivator is straightforward:

private static class PrivateActivator<TArg1>
{
    private static readonly ConcurrentDictionary<Type, Func<TArg1, object>> _constructors = new ConcurrentDictionary<Type, Func<TArg1, object>>();

    public static object CreateInstance(Type type, TArg1 arg1)
    {
        Func<TArg1, object> constructor;
        if (!_constructors.TryGetValue(type, out constructor))
        {
            constructor = (Func<TArg1, object>)type.GetConstructorDelegate(typeof(Func<TArg1, object>));
            _constructors.TryAdd(type, constructor);
        }
        return constructor(arg1);
    }
}

It’s important to note that the parameter types must match exactly the constructor signature as we are not dynamically figuring out inheritance.

Activator.CreateInstance(Type, params object[] args)

Unfortunately, I don’t have an optimized version of this method. If you look in reflector, it is madness. Optimizing it would be quite a challenge and I’ll leave that to someone else to figure out 😉

So now let’s have a look at the implementation of the Type.GetConstructorDelegate() extension method which is really the core of this implementation.

public static Func<TBase> GetConstructorDelegate<TBase>(this Type type)
{
    return (Func<TBase>)GetConstructorDelegate(type, typeof(Func<TBase>));
}

public static Func<object> GetConstructorDelegate(this Type type)
{
    return (Func<object>)GetConstructorDelegate(type, typeof(Func<object>));
}

public static Delegate GetConstructorDelegate(this Type type, Type delegateType)
{
    if (type == null)
        throw new ArgumentNullException("type");

    if (delegateType == null)
        throw new ArgumentNullException("delegateType");

    Type[] genericArguments = delegateType.GetGenericArguments();
    Type[] argTypes = genericArguments.Length > 1 ? genericArguments.Take(genericArguments.Length – 1).ToArray() : Type.EmptyTypes;

    ConstructorInfo constructor = type.GetConstructor(argTypes);
    if (constructor == null)
    {
        if (argTypes.Length == 0)
        {
            throw new InvalidProgramException(string.Format("Type '{0}' doesn't have a parameterless constructor.", type.Name));
        }
        throw new InvalidProgramException(string.Format("Type '{0}' doesn't have the requested constructor.", type.Name));
    }

    DynamicMethod dynamicMethod = new DynamicMethod("DM$_" + type.Name, type, argTypes, type);
    ILGenerator ilGen = dynamicMethod.GetILGenerator();
    for (int i = 0; i < argTypes.Length; i++)
    {
        ilGen.Emit(OpCodes.Ldarg, i);
    }
    ilGen.Emit(OpCodes.Newobj, constructor);
    ilGen.Emit(OpCodes.Ret);
    return dynamicMethod.CreateDelegate(delegateType);
}

So this is pretty straightforward, we find the ConstructorInfo corresponding to the input arguments portion of the delegateType. We then create a dynamic method that matches the delegateType. With the IL generator we load the arguments (if any), call the constructor and return the object.

Summary

So we’ve covered a lot of ground in this article. We’ve optimized most of the CreateInstance methods, cached everything and made sure our implementation was thread-safe by relying on concurrent collections and generic static classes. But how does it perform you might ask? Here’s a chart showing a comparison assuming a warm cache:

image

Advertisements