Blog Home  Home Feed your aggregator (RSS 2.0)  
Performance using reflection - Manuel Abadia's ASP.NET stuff
 
# Tuesday, March 21, 2006

Everybody knows that reflection is slow but I wanted something more measurable than slow so I did some performance tests for the basic things I do with reflection.


The test cases are:


• Create an object
• Call a method with 2 parameters
• Set 4 properties of an object

I implemented each test case with and without reflection so I could compare the results. For the tests I used the Product and ProductDAL classes from my ObjectDataSource tutorial, with the only modification of a new method to the ProductDAL class. Each test case was repeated one million times to get more accurate values. The tests were ran on an AMD 3200 with 1 GB of RAM. The source code for the tests can be found at the end of this post.


The results obtained were:

Creating an object -> 6 times slower using reflection
Calling a method -> 143 times slower using reflection
Setting properties -> 14 times slower using reflection

The full output that the test program generated was:

Constructor
Time ellapsed: Interval: 0,074104 seconds (265260 ticks)

Constructor using reflection
Time ellapsed: Interval: 0,449345 seconds (1608451 ticks)

Method call
Time ellapsed: Interval: 0,025408 seconds (90948 ticks)

Method call using reflection
Time ellapsed: Interval: 3,631799 seconds (13000186 ticks)

Setting properties
Time ellapsed: Interval: 1,562256 seconds (5592166 ticks)

Setting properties using reflection
Time ellapsed: Interval: 22,492780 seconds (80513936 ticks)

Here’s the code for the tests:

using System;

using System.Collections;

using System.Collections.Specialized;

using System.Globalization;

using System.ComponentModel;

using System.Reflection;

 

namespace ConsoleApplication1

{

    class Program

    {

        delegate void MethodToEvaluate(object[] parameters);

 

        static void Main(string[] args)

        {

            long times = 1000000;

 

            // creates the parameter needed for the tests

            IDictionary paramAndValues = new OrderedDictionary();

            paramAndValues.Add("id", "1");

            paramAndValues.Add("name", "product name");

            paramAndValues.Add("description", "product description");

            paramAndValues.Add("price", "100");

            object[] parameters = new object[]{ new Product(), paramAndValues };

 

            // launch the test cases

            EvaluateMethod("Constructor", ConstructorTest, null, times);

            EvaluateMethod("Constructor using reflection", ConstructorTestReflection, null, times);

            EvaluateMethod("Method call", MethodCall, null, times);

            EvaluateMethod("Method call using reflection", MethodCallReflection, null, times);

            EvaluateMethod("Setting properties", SetProperties, parameters, times);

            EvaluateMethod("Setting properties using reflection", SetPropertiesReflection, parameters, times);

 

            Console.ReadLine();

        }

 

        // evaluates a method the specified number of times and print performance information

        static void EvaluateMethod(string testName, MethodToEvaluate method, object[] parameters, long times)

        {

            Console.WriteLine(testName);

 

            IntervalTimer timer = new IntervalTimer();

            timer.Start();

 

            for (long i = 0; i < times; i++) {

                method(parameters);

            }

 

            timer.Stop();

 

            Console.WriteLine("Time ellapsed: " + timer.ToString() + "\n");

        }

 

 

        static void ConstructorTest(object[] parameters)

        {

            Product prod = new Product();

        }

 

        static void ConstructorTestReflection(object[] parameters)

        {

            Activator.CreateInstance(typeof(Product));

        }

 

 

        static void MethodCall(object[] parameters)

        {

            ProductsDAL.TestMethod(0, "test");

        }

 

        static void MethodCallReflection(object[] parameters)

        {

            MethodInfo method = typeof(ProductsDAL).GetMethod("TestMethod", BindingFlags.Public | BindingFlags.Static);

            object[] paramValues = new object[]{ 0, "test" };

            method.Invoke(null, paramValues);

        }

 

 

        static void SetProperties(object[] parameters)

        {

            Product prod = (Product)parameters[0];

            IDictionary values = (IDictionary)parameters[1];

 

            prod.Id = Convert.ToInt32(values["id"]);

            prod.Name = (string)values["name"];

            prod.Description = (string)values["description"];

            prod.Price = Convert.ToDecimal(values["price"]);

        }

 

        static void SetPropertiesReflection(object[] parameters)

        {

            Product prod = (Product)parameters[0];

            IDictionary values = (IDictionary)parameters[1];

 

            SetProperty(prod, "Id", values["Id"]);

            SetProperty(prod, "Name", values["name"]);

            SetProperty(prod, "Description", values["description"]);

            SetProperty(prod, "Price", values["price"]);

        }

 

        #region Helper Methods

 

        static void SetProperty(object obj, string name, object value)

        {

            // searchs for the property

            PropertyInfo prop = typeof(Product).GetProperty(name);

 

            // try to convert a string value to an object (using the type converter)

            object propertyValue = BuildObjectValue(value, prop.PropertyType);

 

            // sets the property value

            prop.SetValue(obj, propertyValue, null);

        }

 

        static object BuildObjectValue(object value, Type destinationType)

        {

            // if we have a value that needs conversion

            if ((value != null) && !destinationType.IsInstanceOfType(value)) {

                Type targetType = destinationType;

 

                // if the value is a string, try to convert it to the target type

                if (value is string) {

                    value = ConvertStringToType((string)value, targetType);

                }

            }

 

            return value;

        }

 

        static object ConvertStringToType(string value, Type destinationType)

        {

            object result = null;

 

            // try to get a type converter

            TypeConverter converter = TypeDescriptor.GetConverter(destinationType);

            if (converter == null) {

                return value;

            }

 

            // try to convert the string using the type converter

            result = converter.ConvertFromString(null, CultureInfo.CurrentCulture, value);

 

            return result;

        }

 

        #endregion

    }

}

 

Source code: ReflectionTests.zip (4.28 KB)
Tuesday, March 21, 2006 6:51:37 PM (Romance Standard Time, UTC+01:00)  #    Comments [3]   ASP.NET  | 
Copyright © 2014 Manuel Abadia. All rights reserved.
DasBlog 'Portal' theme by Johnny Hughes.