Vagif Abilov's blog on .NET

Don’t use Activator.CreateInstance or ConstructorInfo.Invoke, use compiled lambda expressions

For a long time I’ve been under impression that rule engine that comes with Microsoft Windows Workflow Foundation is slow, very slow. We used it to execute some of our business rules, and soon found out that rule processing slows down application execution. What was strange is that the rules were really simple and it was hard to believe that an industry-strength rule engine uses so long time on processing them.

Eventually I ran a profiler, and it immediately showed where the time was spent. In fact it was not the actual rule validation but preparation for it: instantiation of the WF rule parser. The parser class is not public, so we used a trick to obtain its instance: retrieved its non-public constructor information via reflection and then called Invoke.

This was sloooow. So slow that we noticed it in our integration tests. What made it noticeable is that after we converted some of our business rules to use WF rule engine, we were encouraged by results and move more rules to use the same techinque. In the end rule validation was called many times during a single business operation, and performance deteriorated.

My first approach to this issue was to cache validated rules, and it worked. The total time to execute integration tests was reduced by 50%. However, I was not quite happy with the situation: we have various places where objects are instantiated using reflection, caching is not always possible and in general complicates component design. Recently I reviewed the code of StructureMap (I like reading good code), and remembered that it no longer used reflection and instead instantiated dependencies using compiled lambda expressions.

Roger Alsing in this post presented a generic method that can be used as a replacement for constructor method invocation. The essence of the method is in it’s last three lines:

// 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), newExp, param);              

// Compile it
ObjectActivator compiled = (ObjectActivator)lambda.Compile();

Although lambda expressions are part of LINQ (and you have to import System.Linq.Expressions namespace to manage them), as we can see from this example, they can be very useful to solve core language tasks, such as object instantiation.

But what is the gain? The gain is huge bringing the performance close to the speed of native IL code. I wrote a few tests to measure performance of object creation in different scenarios: by calling ‘new’ constructor, Activator.CreateInstance, ConstructorInfo.Invoke and using compiled lambda expression. Here are the results:

DefaultConstructor_Activator: (0,20 ms per 1000 calls)
DefaultConstructor_CompiledExpression: (0,04 ms per 1000 calls)
DefaultConstructor_Invoke: (1,07 ms per 1000 calls)
DefaultConstructor_New: (0,02 ms per 1000 calls)
DefaultConstructor_NotCompiledExpression: (169,00 ms per 1000 calls)
NonDefaultConstructor_Activator: (3,39 ms per 1000 calls)
NonDefaultConstructor_CompiledExpression: (0,07 ms per 1000 calls)
NonDefaultConstructor_Invoke: (1,57 ms per 1000 calls)
NonDefaultConstructor_New: (0,02 ms per 1000 calls)
NonDefaultConstructor_NotCompiledExpression: (293,00 ms per 1000 calls)

Results says it all, especially when arranged in a graph.

Chart

I removed from the graph the results for not compiled lambda expressions, because they make other figures insignificant. But it is important to remember that compilation should be performed only once, so the code should be carefully reviewed to avoid occasional recompilcation of lambdas.

P.S. The title of this blog post may look provocative, and of course I don’t really mean somebody should completely stop using Activator.CreateInstance. Compilation of labmda expressions is expensive enough to limit it’s practical use. But there are certain use cases (like IoC frameworks) when it gives clear performance advantage.

Comments

Johnny said:

that a good technical article for introduct the compiled lambda expressions's advantage.

and I have some question? you mentioned in the article that you ran a profiler to see where the time the application was spent. I want to know what's the profiler? and where I can find it?

please answer me, and can contact me with this email:

zhoujinbo211434@126.com

# April 11, 2010 8:00 AM

Vagif Abilov said:

Johnny,

The profile I used is Red-Gate ANTS Profiler. You can find more about it here: www.red-gate.com/.../index.htm

Hope this help.

# April 15, 2010 5:24 PM

Sathish said:

Can you please share the sample code for compiled lambda expressions

# July 28, 2010 7:49 AM

Vagif Abilov said:

Sathish,

Have a look at Roger Alsing's example that is referenced in my post.

# July 29, 2010 9:11 AM

Eder Nucci said:

Thank you for this INCREDIBLE information. Good to see people understanding daily problems with intelligence.

# November 30, 2010 7:56 PM

Bob Kaine said:

I think this may help me.

I'm trying to create the name of the object that was passed to a method inside of a for loop.

I'm creating an extensible WebMethod that accepts several parameters. The very first parameter contains the name of the "View" the user wants to retrieve data from. The view is stored in .Config file and the value contains the database, storedproc and number of parameters.

When I build the CommandType.StoredProcedure and begin adding parameters I want to loop from 1 to number of parameters.

for (int i = 1; i < numParams; i++)

       {

           string dbParam = "param" + i;

           string inputParam = "param" + i;

           cmd.Parameters.Add(dbParam, OracleDbType.Varchar2).Value = inputParam;

       }

Obviously, in the code above the string object inputParam contains "param1" or "param2", etc. and I actually need it inputParam to be equal to param1 string object that was passed to the method.

Sorry so long...

# December 1, 2010 3:05 PM

Vagif Abilov's blog on .NET said:

tAbout a year ago I blogged about different methods of object instantiation and that compiled lambda

# April 18, 2011 2:58 PM

Pooya said:

have you tried using a Static Delegate?

e.g.

stackoverflow.com/.../how-to-instantiate-a-generic-type-with-multiple-input-parameters

compiled lambda vs static delegate?

# June 17, 2011 8:40 AM

Arvind said:

Is the Compile() operation slower or faster? I am assuming the performance is accounted without including the compile time? In scenarios where multiple instances of different types are necessary and where type of object is determined at runtime, Would it be lot slower having compile operation everytime than Activator.CreateInstance?

(Reposted from Stack Overflow article for this Q, stackoverflow.com/.../activator-createinstance-performance-alternative)

# March 14, 2012 6:16 PM

giammin said:

i get really different results with this test: http://pastebin.com/Lf8FHCjA

00:00:00.0008552  new

00:00:00.0027870  Activator

00:00:00.0230817  constructorInfo.Invoke

00:00:00.0340304  constructorInfo.Invoke GetUninitializedObject

00:00:01.2327014  DynamicMethod

00:00:00.9903088  DynamicMethod with Delegate

00:00:01.5705766  Expression

# May 3, 2012 4:33 PM

Holi said:

I need to create 1 instance of each of about 100 different classes (just passing the type to the creation method); I therefore need to compile the lambda expression for each of the classes. I assume in that case the speed is not better but much worse than with using CreateInstance().

Is this correct or incorrect (I cannot find what led to the comparison chart - is this always a one-call measurement including the compilation of the lambda expression, or is it just the creation itself that was measured?).

# October 31, 2012 1:25 PM

Vagif Abilov said:

Holi,

Your assumption is correct. Compilation of labmda expressions gives higher overhead than instantiation using reflection, so if all classes are different lamda compilation does not make sense.

# November 1, 2012 5:17 AM

Bruce Pierson said:

This is great when you need to create a bunch of really small objects.

In using it to construct an object of any reasonable complexity (e.g., 1 or 2 levels of inheritance, a little bit of state that pre-initializes), though, the differences are far less dramatic. I found that creating 100,000 of my Sale domain records, for example:

Activator with parameters: 323 ms

Compiled lambda: 164 ms

Twice as good, to be sure, but when we are usually only creating objects at most a few hundred at a time (usually after some database query), the difference is vanishingly miniscule. 3 ms vs. 2 ms to create a list of 1000 records? Look elsewhere for optimization in that domain.

But as I said, the difference is impressive for very small, simple instances.

# February 9, 2013 7:11 AM

JinaCookies said:

How to use it?

Original:

string className = xml_path + ".RzCodeTypeDal";

return (IRzCodeType)Assembly.Load(path).CreateInstance(className);

Future:?

# May 23, 2013 8:48 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 


Please add 4 and 7 and type the answer here: