Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is reflection faster than object Initialization?

Tags:

c#

reflection

  1. Sorry for non computer science terms (self taught)
  2. Sorry incorrect terminology (Anyone willing to edit, please do, (self taught))

I searched as much as I could, with my limited knowledge of terminology for what I was searching for, but I could not find and answer to the question I was after.

I was surprised to find that filling an object with data was faster through Reflection than using object Initialization.

I made a test console app for this purpose. First the test class,

class TestClass
    {
        public string PropertyOne { get; set; }
        public string PropertyTwo { get; set; }
        public string PropertyThree { get; set; }
        public string PropertyFour { get; set; }
        public string PropertyFive { get; set; }
        public string PropertySix { get; set; }
        public string PropertySeven { get; set; }
        public string PropertyEight { get; set; }
        public string PropertyNine { get; set; }
        public string PropertyTen { get; set; }
    }
}

Then the methods to get data, First is reflection,

public static void ReflectionTest()
    {
        for (int i = 0; i < 10000000; i++)
        {
            TestClass testClass = new TestClass();
            Type type = testClass.GetType();
            PropertyInfo[] properties = type.GetProperties();
            foreach (var propertyInfo in properties)
            {
                switch (propertyInfo.Name)
                {
                    case nameof(testClass.PropertyOne):
                        propertyInfo.SetValue(testClass, "PropertyOne" + i);
                        break;
                    case nameof(testClass.PropertyTwo):
                        propertyInfo.SetValue(testClass, "PropertyTwo" + i);
                        break;
                    case nameof(testClass.PropertyThree):
                        propertyInfo.SetValue(testClass, "PropertyThree" + i);
                        break;
                    case nameof(testClass.PropertyFour):
                        propertyInfo.SetValue(testClass, "PropertyFour" + i);
                        break;
                    case nameof(testClass.PropertyFive):
                        propertyInfo.SetValue(testClass, "PropertyFive)" + i);
                        break;
                    case nameof(testClass.PropertySix):
                        propertyInfo.SetValue(testClass, "PropertySix" + i);
                        break;
                    case nameof(testClass.PropertySeven):
                        propertyInfo.SetValue(testClass, "PropertySeven" + i);
                        break;
                    case nameof(testClass.PropertyEight):
                        propertyInfo.SetValue(testClass, "PropertyEight" + i);
                        break;
                    case nameof(testClass.PropertyNine):
                        propertyInfo.SetValue(testClass, "PropertyNine" + i);
                        break;
                    case nameof(testClass.PropertyTen):
                        propertyInfo.SetValue(testClass, "PropertyTen" + i);
                        break;
                }                    
            }
            TestClasses.Add(testClass);
        }
    }

Next is Initialization of Object,

public static void InitializationTest()
    {
        for (int i = 0; i < 10000000; i++)
        {
            TestClass testClass = new TestClass
            {
                PropertyOne = "PropertyOne" + i,
                PropertyTwo = "PropertyTwo" + i,
                PropertyThree = "PropertyThree" + i,
                PropertyFour = "PropertyFour" + i,
                PropertyFive = "PropertyFive)" + i,
                PropertySix = "PropertySix" + i,
                PropertySeven = "PropertySeven" + i,
                PropertyEight = "PropertyEight" + i,
                PropertyNine = "PropertyNine" + i,
                PropertyTen = "PropertyTen" + i
            };
            TestClasses.Add(testClass);
        }
    }

And the test code

static List<TestClass> TestClasses { get; set; } = new List<TestClass>();

    static void Main(string[] args)
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();
        ReflectionTest();
        Console.WriteLine($"Reflection Test time: {sw.Elapsed}");
        sw.Reset();
        sw.Start();
        InitializationTest();
        Console.WriteLine($"Initialization Test time: {sw.Elapsed}");
        sw.Stop();
    }

Using this code reflection was 20% faster using object Initialization. What is the reason for this?

EDIT: Adding TestClasses.Clear(); to the code shows that 'object Initialization' is nearly twice as fast. Thanks for the replies and comments.

like image 269
KyloRen Avatar asked Apr 12 '26 20:04

KyloRen


1 Answers

Such measurements don't make sense - otherwise everyone would use reflection instead of object instances.

The main reason why results are confusing is that all items are being added to the same List. Invoke tests in different order and InitializationTest performs better.

static void Main(string[] args)
{
    Stopwatch sw = new Stopwatch();

    sw.Start();
    InitializationTest();
    Console.WriteLine($"Initialization Test time: {sw.Elapsed}");
    sw.Stop();
    sw.Reset();

    sw.Start();
    ReflectionTest();
    Console.WriteLine($"Reflection Test time: {sw.Elapsed}");
    sw.Stop();
    sw.Reset();

    Console.ReadLine();
}

As Matthew Watson put in a comment: "better still, don't use the lists at all as part of the timing. We're supposed to be timing how long it takes to create object - not how long it takes to fill a very large list."


Reflection test included unnecessary costs: repeated GetProperties invokations, testing conditions in switch

public static void ReflectionTest()
{
    PropertyInfo[] properties = typeof(TestClass).GetProperties();
    for (int i = 0; i < 10000000; i++)
    {
        TestClass testClass = new TestClass();
        foreach (var propertyInfo in properties)
        {
            propertyInfo.SetValue(testClass, propertyInfo.Name + i);
        }
        TestClasses.Add(testClass);
    }
}
like image 162
ASh Avatar answered Apr 15 '26 09:04

ASh