brady gaster

yadnb

Benchmarking the Provider Goodieness

Just to be... well.. anal about the performance benefits of the caching idea, I ran my example ASPX page again, this time writing out the Environment.TickCount for the start and the end of the process. Without caching - that is, using Activator.CreateInstance - the process took 591 milliseconds. With the constructor being cached, I tried 3 results. The first? 20 milliseconds. The second? 0. The third? 10.

Nifty.

Comments

Frans Bouma said:

Be aware of the fact that Activator.CreateInstance() most likely uses reflection, which can be slow.

You can also consider a factory pattern implementation.
# November 26, 2003 4:43 PM

Rob Howard said:

Small perf. gain there ;)
# November 26, 2003 5:00 PM

brady gaster said:

oh yeah, teensy. itsy-bitsy. weenie-teenie.

and thanks frans. i think i'm going to couple your comment with another i received from the original posting and create yet one more example.
# November 26, 2003 5:04 PM

Sean said:

Can you post the exact code you benchmarked with? I'd like to see the code that gives some a vast difference between the methods

I wrote my own benchmark...


Type type = typeof(Person);
ConstructorInfo ctor = type.GetConstructor(Type.EmptyTypes);

StopWatch sw = new StopWatch();
for (int a = 0; a < 3; a++)
{
for (int i = 0; i < 1000000; i++)
{
Person person = (Person) ctor.Invoke(null);
}
Console.WriteLine("Objects Created: " + Person.getCount());
Console.WriteLine("Execution Time: " + sw.ElapsedMilliseconds());
sw.Reset();
}

for (int a = 0; a < 3; a++)
{
for (int i = 0; i < 1000000; i++)
{
Person person = (Person) Activator.CreateInstance(type);
}
Console.WriteLine("Objects Created: " + Person.getCount());
Console.WriteLine("Execution Time: " + sw.ElapsedMilliseconds());
sw.Reset();
}

for (int a = 0; a < 3; a++)
{
for (int i = 0; i < 1000000; i++)
{
Person person = (Person) ClassLoader.newInstance(type);
}
Console.WriteLine("Objects Created: " + Person.getCount());
Console.WriteLine("Execution Time: " + sw.ElapsedMilliseconds());
sw.Reset();
}



StopWatch is a wrapper class to the win32 performance timers.


the first loop runs on invoking an already constructed ConstructorInfo object.

Second is Activator,

third is my caching ClassLoader object:

public static Object newInstance(Type type)
{
if (type == null)
throw new ApplicationException("Type supplied cannot be null");

string key = type.FullName;

ConstructorInfo ctor = cache[key] as ConstructorInfo;
if (ctor == null)
{
ctor = type.GetConstructor(Type.EmptyTypes);
cache[key] = ctor;
}
return ctor.Invoke(null);
}

here is the output:


Objects Created: 1000000
Execution Time: 681.5
Objects Created: 2000000
Execution Time: 659.9
Objects Created: 3000000
Execution Time: 668.5
Objects Created: 4000000
Execution Time: 1136.6
Objects Created: 5000000
Execution Time: 1193.8
Objects Created: 6000000
Execution Time: 1160.7
Objects Created: 7000000
Execution Time: 1058.3
Objects Created: 8000000
Execution Time: 1070
Objects Created: 9000000
Execution Time: 1072.6


as you can see.. the constructorinfo invoke method is the fastest, followed by the cached constructorinfo, flowed closely by Activator.CreateInstance....

given the fact that the difference in speed between the two latter methods is minimal, you may as well just use Activator.CreateInstance, and save yourself some programming/worry
# December 9, 2003 9:01 AM
Leave a Comment

(required) 

(required) 

(optional)

(required)