Three ways to create new …

With all the fuss with AOP and a zillion other acronyms, did you ever wonder what performance impact it would entail to create instances of objects dynamically, at runtime ?

For the past few months, I’ve been using Dynamic Class Loading extensively, in much of my code.
I did that, using Activator.CreateInstance(...), so that i could initialize from an xml file, where I specified my class assembly, and the class I wanted instances of.

Now, I do realize that by using Activator.CreateInstance(...) I’m placing an overhead to the system. However, I felt that the added flexibility was reason enough.

So today, I thought of a third way. I could retrieve the default-no-args constructor info by using reflection, and invoke that ConstructorInfo reference whenever I needed a new instance of a class. How would that compare performance-wise with the Activator method, and then with the direct instantiation ?

So, I’ve written a small test app, less than 20 lines of code, measuring the ticks it takes to construct the simplest of objects. I affectionately called my empty class MyObject.

The first way to construct is the simple way. Directly. here’s the method:

static MyObject CreateDirect() {
return new MyObject();
}

… nuclear science huh?

Ok, the second way id the Activator way. Source please:

static MyObject CreateByActivator(){
ObjectHandle obj = Activator.CreateInstance("Tests", "Tests.MyObject");
return (MyObject) obj.Unwrap();
}

A bit more involved, innit ? Also, it requires using the System.Runtime.Remoting namespace.

The third way is to use the type, get the constructor info for the (supposedly present) no-args constructor, and invoke that. Source:

static MyObject CreateByReflection(){
Type myType = typeof(MyObject);
ConstructorInfo constr = myType.GetConstructor(new System.Type[0]);
return (MyObject) constr.Invoke(new object[0]);
}

That’s all very nice so far, no ? So, here’s the small Main(args[]) method that runs the three methods, and returns the times required to obtain an instance of myObject in each case:

static void Main(string[] args)
{
long startTicks, endTicks;

// Create directly first ...
startTicks = DateTime.Now.Ticks;
MyObject obj = CreateDirect();
endTicks = DateTime.Now.Ticks;
Console.WriteLine("Called direct. Ticks: {0}", (endTicks-startTicks));

// Create by activator ...
startTicks = DateTime.Now.Ticks;
obj = CreateByActivator();
endTicks = DateTime.Now.Ticks;
Console.WriteLine("Called by activator. Ticks: {0}", (endTicks-startTicks));

// Create by reflecting constructor ...
startTicks = DateTime.Now.Ticks;
obj = CreateByReflection();
endTicks = DateTime.Now.Ticks;
Console.WriteLine("Called by reflection. Ticks: {0}", (endTicks-startTicks));

Console.ReadLine();
}

Fair is fair :) Let’s see the output in my machine (PIII 2.7Ghz, 1Gb RAM).

Called direct. Ticks: 0
Called by activator. Ticks: 156258
Called by reflection. Ticks: 0

Oh boy !!! It would seem that by using Activator, I’m more or less … 156258 times slower than by using a direct instantiation! Even more, it seems that if I use Reflection instead, I’m as fast as using direct instantiation! Have I been so terribly wrong in my Dynamic Class Instantiation code in the past ?

Well, after a brief pause, and a gasp for air, it hits me. My reflection method doesn’t actually take the time to create the Type object from a couple of strings, like the Activator does. So, I decided to change the method to do that. In any way, if I were to change my existing dynamic class loading code I’d have to add that step as well. So, here’s the new code:

static MyObject CreateByReflection2(){
Type myType = Type.GetType("Tests.MyObject");
ConstructorInfo constr = myType.GetConstructor(new System.Type[0]);
return (MyObject) constr.Invoke(new object[0]);
}

Now, after a couple of runs, I observed a rather weird phenomenon. The Activator method seems to return in around 156280 ticks every once in a while. All other times it returns in 0 ticks, like the others ! :S And the new Reflection-using method always returns in 0 ticks anyway.

So, I moved all the testing code from the Main method into a new one, called Test(), and decided to call it in a loop for a few times whilst printing out the response times, in an effort to get a more accurate measure.

I’ll print here the output of a 3-times instantiation loop, because I’ve no intention to fill this page up with console output. However, the same pattern occurs with a larger number of repetitions as well.

So, observe:

Called direct. Ticks: 0
Called by activator. Ticks: 156247
Called by reflection. Ticks: 0
Called direct. Ticks: 0
Called by activator. Ticks: 0
Called by reflection. Ticks: 0
Called direct. Ticks: 0
Called by activator. Ticks: 0
Called by reflection. Ticks: 0

After the first it is called, the Activator method will always return in 0 ticks. I suspect that the Activator somehow caches all the data it requires for instantiating my object, and holds on to that for a while, before discarding it and so on and so forth.

I also must point out that the Reflection method is not as flexible as the Activator one, not being able to specify the parent assembly from I want the instance to come from (I suspect that by placing my assembly in the GAC i’d be ok, but what if I’ve two versions of my assembly in the GAC at the same time?)

In the next few weeks I’ll try to answer all these questions, and I’ll be sure to post them out here in blogworld as well :)

You can find the sources for my little project, here.

Comments are closed.