Showing posts with label method. Show all posts
Showing posts with label method. Show all posts

Monday, May 3, 2010

Genetic Programming: C# Reflection Performance and Improvements on Methods and Fields

I've already done three posts on reflection and the performance of the various method invocation approaches, so if we've learned anything from those posts it's that when it comes to Genetic Programming we can't use methods to return constants (like it wasn't obvious). If we want to have GP's that can keep up with the real-time market and are flexible enough to modify on the fly, then we should look for optimal performance.

I'd say that about 99% of all the computation occurring in a GP is in the execution of individual specimens (i.e. evaluating their expression trees). If we add functions and constants that are going to be evaluated millions of times, then these functions and constants should be REALLY fast! Using reflection to discover the fields, properties and methods that can be used by the GP does give us the ability to change the supported functions on-the-fly, but that ability comes at a price.

Using reflection to access the values of a field or a property is done in the same amount of ticks as accessing the field or property directly from the object:



The code that was used to get the above statistics is this:

static void VariablesAndPropertiesTest()
{
int numRuns = 100 * 1000;
var val = 0.0;
Functions fn = new Functions();
FieldInfo numTwo = fn.GetType().GetField("constNumTwo");
PropertyInfo numOne = fn.GetType().GetProperty("ConstNumOne");

Console.WriteLine("Reflection field");
_stopwatch.Start();
for (int i = 0; i < numRuns; ++i)
{
val = (double)numTwo.GetValue(fn);
}
_stopwatch.Stop();
Console.WriteLine("Avg Ticks \t " + _stopwatch.ElapsedTicks / numRuns);

Console.WriteLine("Direct field");
_stopwatch.Start();
for (int i = 0; i < numRuns; ++i)
{
val = fn.constNumTwo;
}
_stopwatch.Stop();
Console.WriteLine("Avg Ticks \t " + _stopwatch.ElapsedTicks / numRuns);

Console.WriteLine("Reflection property");
_stopwatch.Start();
for (int i = 0; i < numRuns; ++i)
{
val = (double)numOne.GetValue(fn, null);
}
_stopwatch.Stop();
Console.WriteLine("Avg Ticks \t " + _stopwatch.ElapsedTicks / numRuns);

Console.WriteLine("Direct property");
_stopwatch.Start();
for (int i = 0; i < numRuns; ++i)
{
val = fn.ConstNumOne;
}
_stopwatch.Stop();
Console.WriteLine("Avg Ticks \t " + _stopwatch.ElapsedTicks / numRuns);

Console.WriteLine("Direct method");
_stopwatch.Start();
for (int i = 0; i < numRuns; ++i)
{
val = fn.GPConstNumZero();
}
_stopwatch.Stop();
Console.WriteLine("Avg Ticks \t " + _stopwatch.ElapsedTicks / numRuns);
}