I was getting ready to write some code that will apply rules to an object using reflection, when I realized I could do the same thing using IronPython. My only concern was the performance implications, because what I was doing needed to be fast.
Here are the results of basically setting properties on an object using both python and reflection.
Here is the code. Nothing fancy. I didn’t notice that there is a hit with the initial run, but after that IronPython is much faster. If you look at the code you will notice that the time does not include setting up the engine, scope, etc. You can play with those yourself, because here is the code.
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Running 1000");
RunIteration(1000);
Console.WriteLine("Running 10000");
RunIteration(10000);
Console.WriteLine("Running 100000");
RunIteration(100000);
Console.WriteLine("Running 1000000");
RunIteration(1000000);
Console.WriteLine("Running 10000000");
RunIteration(10000000);
Console.WriteLine("Running 10000000");
RunIteration2(10000000);
Console.ReadLine();
}
static void RunIteration(int iterations)
{
Console.WriteLine("Reflection Iteration.");
TestReflection(iterations);
Console.WriteLine("Python Iteration.");
TestPython(iterations);
Console.WriteLine("Testing Complete.");
Console.WriteLine();
}
static void RunIteration2(int iterations)
{
Console.WriteLine("Reflection Iteration 2.");
TestReflection(iterations);
Console.WriteLine("Python Iteration 2.");
TestPython2(iterations);
Console.WriteLine("Testing Complete.");
Console.WriteLine();
}
static void TestReflection(int iterations)
{
var test = new TestClass();
var type = test.GetType();
var st = new Stopwatch();
st.Start();
for (var i = 0; i < iterations; i++)
{
type.GetProperty("Id").SetValue(test, 1, null);
type.GetProperty("Name").SetValue(test, "New Name", null);
}
st.Stop();
Console.WriteLine("Time {0} ms", st.ElapsedMilliseconds);
}
static void TestPython(int iterations)
{
var engine = Python.CreateEngine();
var source = engine.CreateScriptSourceFromFile("test.py");
var scope = engine.CreateScope();
var test = new TestClass();
source.Engine.SetVariable(scope, "test", test);
source.Engine.SetVariable(scope, "iterations", iterations);
var st = new Stopwatch();
st.Start();
source.Execute(scope);
st.Stop();
Console.WriteLine("Time {0} ms", st.ElapsedMilliseconds);
}
static void TestPython2(int iterations)
{
var engine = Python.CreateEngine();
var source = engine.CreateScriptSourceFromFile("test2.py");
var scope = engine.CreateScope();
var test = new TestClass2();
source.Engine.SetVariable(scope, "test", test);
source.Engine.SetVariable(scope, "iterations", iterations);
var st = new Stopwatch();
st.Start();
source.Execute(scope);
st.Stop();
Console.WriteLine("Time {0} ms", st.ElapsedMilliseconds);
}
}
public class TestClass
{
public int Id { get; set; }
public string Name { get; set; }
}
public class TestClass2
{
public int Id2 { get; set; }
public string Name2 { get; set; }
}