Linq Expressions – Creating objects

This post shows how you can use Linq expression trees to replace Activator.CreateInstance.

but first, please note that this is a followup on Oren’s post so read it before you read mine:
http://www.ayende.com/Blog/archive/2008/02/27/Creating-objects–Perf-implications.aspx

In C#3 we can use Linq expression trees to solve this problem to.
I’m not saying that it is a better or faster solution than Oren’s IL emit version.
The IL emit is completely optimized for what it is supposed to do, so its hard to beat.
This is just an alternative if you are a bit affraid of IL emit ;-), Linq expressions are just easier to understand for most people. 

So how is it done?
First we need a delegate declaration:

delegate T ObjectActivator<T>(params object[] args);

We will use this delegate in order to create our instances.
We also need a generator that can compile our delegates from expression trees:

public static ObjectActivator<T> GetActivator<T>
    (ConstructorInfo ctor)
{
    Type type = ctor.DeclaringType;
    ParameterInfo[] paramsInfo = ctor.GetParameters();                  

    //create a single param of type object[]
    ParameterExpression param =
        Expression.Parameter(typeof(object[]), "args");
 
    Expression[] argsExp =
        new Expression[paramsInfo.Length];            

    //pick each arg from the params array 
    //and create a typed expression of them
    for (int i = 0; i < paramsInfo.Length; i++)
    {
        Expression index = Expression.Constant(i);
        Type paramType = paramsInfo[i].ParameterType;              

        Expression paramAccessorExp =
            Expression.ArrayIndex(param, index);              

        Expression paramCastExp =
            Expression.Convert (paramAccessorExp, paramType);              

        argsExp[i] = paramCastExp;
    }                  

    //make a NewExpression that calls the
    //ctor with the args we just created
    NewExpression newExp = Expression.New(ctor,argsExp);                  

    //create a lambda with the New
    //Expression as body and our param object[] as arg
    LambdaExpression lambda =
        Expression.Lambda(typeof(ObjectActivator<T>), newExp, param);              

    //compile it
    ObjectActivator<T> compiled = (ObjectActivator<T>)lambda.Compile();
    return compiled;
}

It’s a bit bloated but keep in mind that this version is completely dynamic and you can pass any constructor with any arguments to it.

Once we have the generator and the delegate in place, we can start creating instances with it:

ConstructorInfo ctor = typeof(Created).GetConstructors().First();
ObjectActivator<Created> createdActivator = GetActivator<Created>(ctor);
...
//create an instance:
Created instance = createdActivator (123, "Roger");

 And that’s it.
I haven’t done any benchmarking to compare it to Oren’s IL emit version, but I would guess that it is almost but not quite as fast.

Benchmark – Creating 1000 000 instances:

Activator.CreateInstance: 8.74 sec
Linq Expressions:         0.104 sec

My benchmarks is w/o the .ToString() stuff that is included in Oren’s post.. so don’t compare my numbers to his.. it’s done on a different machine too.

//Roger

30 Comments

  1. Marc Gravell says:

    I’m going to upset you again… MiscUtil; there are some extension methods on Type (in “TypeExt”) that might look familiar…

    But good to see that I’m not the only person crazy enough to be using Expressions in this way!

  2. Roger Alsing says:

    I tend to use and abuse new features when I find them.
    Its the best way to learn new techniques, atleast for me.

    And atleast this code wasnt _that_ similair.
    The generic operator code was more scary :-)

    Btw. you forgot to add field readers in your lib ;-)
    http://rogeralsing.com/2008/02/26/linq-expressions-access-private-fields/

  3. Marc Gravell says:

    I’m of the view that we are making good and appropriate use of some under-advertised functionality. If you’ve ever written IL, then you’ll know how much of a gift this is by comparison! My only gripe is that you can’t use property-setters (except for in initializers) – a shame, but I can appreciate why. Still; useful anyway – C# goes “meta”.

  4. Marc Gravell says:

    > Btw. you forgot to add field readers in your lib

    Not sure if that was a suggestion or a plug; if the former, we simply didn’t need them (besides, I’m not a big fan of too much knowledge of fields outside the declaring class).

    Re setters… obviously Expression doesn’t support this; but if you *need* fast “set” access to fields, you might consider some variant of HyperDescriptor:
    http://www.codeproject.com/KB/cs/HyperPropertyDescriptor.aspx
    This also has the advantage of working on 2.0; at the moment it targets properties, but as the metrics show, it doesn’t exactly suffer for this…

  5. Roger Alsing says:

    Yes, I’ve had my fair share of IL emit when I wrote NAspect (subclass proxy based AOP framework for .NET)

    I had to use reflector and dissassemble code all the time to get my emits right.
    Especially the pain with types that need boxing etc.
    “Should I box now or is it already boxed?”

    That kind of stuff was a real PITA.

  6. Gustavo Guerra says:

    Your approach is only slightly slower than generating the il

    With 1000000 iterations I get this:
    constructor.Invoke() -> 01.7241s
    lambda expression -> 00.0186s
    dynamicmethod il -> 00.0154s

    What’s curious is that if you lower that number to 10000, the lambda expression is faster
    constructor.Invoke() -> 00.01738s
    lambda expression -> 00.00026s
    dynamicmethod il -> 00.00044s

    Here’s the code:

    using System;
    using System.Diagnostics;
    using System.Linq.Expressions;
    using System.Reflection;
    using System.Reflection.Emit;

    public interface IXPTO {
    }

    public class XPTO : IXPTO {
    public XPTO() {}
    }

    public class BenchMark {

    public static void Main() {

    ConstructorInfo constructor = typeof(XPTO).MakeGenericType(typeof(int)).GetConstructor(Type.EmptyTypes);
    Func<IXPTO> f1 = () => (IXPTO)constructor.Invoke(new object[0]);
    Func<IXPTO> f2 = (Func<IXPTO>)Expression.Lambda(Expression.Convert(Expression.New(constructor), typeof(IXPTO))).Compile();
    DynamicMethod method = new DynamicMethod(“CreateIntance”, typeof(IXPTO), Type.EmptyTypes);
    ILGenerator gen = method.GetILGenerator();
    gen.Emit(OpCodes.Newobj, constructor);
    gen.Emit(OpCodes.Ret);
    Func<IXPTO> f3 = (Func<IXPTO>)method.CreateDelegate(typeof(Func<IXPTO>));

    int iterations = 1000000;

    Stopwatch watch = Stopwatch.StartNew();
    for (int i = 0; i < iterations; ++i) {
    f1();
    }
    Console.WriteLine(watch.Elapsed);
    watch = Stopwatch.StartNew();
    for (int i = 0; i < iterations; ++i) {
    f2();
    }
    Console.WriteLine(watch.Elapsed);
    watch = Stopwatch.StartNew();
    for (int i = 0; i < iterations; ++i) {
    f3();
    }
    Console.WriteLine(watch.Elapsed);
    Console.ReadLine();
    }
    }

    1. Tony THONG says:

      var method = new DynamicMethod(“CreateIntance”, typeof(IXPTO), new Type[] { typeof(object) }, typeof(XPTO), true); //Unused argument in first place to avoid generated combo (ldnull + pop + jmp)
      var gen = method.GetILGenerator();
      gen.Emit(OpCodes.Newobj, constructor);
      gen.Emit(OpCodes.Ret);
      var f3 = method.CreateDelegate(typeof(Func), null) as Func; //Set null to unused argument.
      f3(); //First call must be done before test.

  7. Jegatheeswaran M says:

    In the following line

    //create an instance:
    Created instance = createdActivator (123, “Roger”);

    createdActivator doesn’t allow null values. How to make this method to accept null values too?

    When used the following line of code
    Created instance = createdActivator(null, “Jegan”);
    It is throwing object reference error.

    Can you please help me to resolve this?

  8. Jimmi says:

    Really awesome

  9. Sandy says:

    Awesome article…

  10. Thomas Zeman says:

    Have you checked this out with .NET4.5? On my machine the compiled expression version becomes about 4-5times slower than on .NET3.5.

  11. Roger Alsing says:

    @Thomas Zeman , I havent tried this, but I would guess this is because of something like intellitrace or some other enhanced debugging feature.
    I would be very surprised if it performes worse when the code is compiled in releasemode and started w/o debugging.

  12. Ron says:

    I’m actually seeing the same behavior as Thomas Zeman using .NET 4.5. I tried creating and populating 40,000 objects, and while release mode shaved about 200ms off, it was still about 20x slower than Activator.

  13. I’ve tested this with the creation of 100,000 object on .NET 4.5, i am noticing the slowdown too:

    Expressions: 00:00:13.8150164
    Activator: 00:00:00.1139471

  14. yuvalos says:

    I have tested this as well, and received that Activator was 9x faster then Expressions. Has anything changed in the framework?

  15. Carsten says:

    Really nice blog. I have a last question: if I do not have a Type-argument (T) but only a type-param (so to say I´m not within a generic context and therefor cannot call GetActivator<typeof(MyType)>), how may I point to that method? I suppose using relfection MakeGenericMethod and tnan calling Invoke on that method is quite slow, so do you have another suggestion?

  16. jjxtra says:

    Not seeing the slowdown with expressions in net core 3. It can do 10 million creations of a simple object in 0.25 on threadripper 1950x. Activator.CreateInstance takes almost 7 seconds for 10 million creations, so still a big win.

Leave a Reply to Roger Alsing Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s