Performance of Object.GetType()

前端 未结 7 1826
花落未央
花落未央 2020-12-05 03:44

We have lots of logging calls in our app. Our logger takes a System.Type parameter so it can show which component created the call. Sometimes, when we can be bothered, we

7条回答
  •  我在风中等你
    2020-12-05 04:20

    I strongly suspect that GetType() will take significantly less time than any actual logging. Of course, there's the possibility that your call to Logger.Log won't do any actual IO... I still suspect the difference will be irrelevant though.

    EDIT: Benchmark code is at the bottom. Results:

    typeof(Test): 2756ms
    TestType (field): 1175ms
    test.GetType(): 3734ms
    

    That's calling the method 100 million times - the optimisation gains a couple of seconds or so. I suspect the real logging method will have a lot more work to do, and calling that 100 million times will take a lot longer than 4 seconds in total, even if it doesn't write anything out. (I could be wrong, of course - you'd have to try that yourself.)

    In other words, as normal, I'd go with the most readable code rather than micro-optimising.

    using System;
    using System.Diagnostics;
    using System.Runtime.CompilerServices;
    
    class Test
    {
        const int Iterations = 100000000;
    
        private static readonly Type TestType = typeof(Test);
    
        static void Main()
        {
            int total = 0;
            // Make sure it's JIT-compiled
            Log(typeof(Test)); 
    
            Stopwatch sw = Stopwatch.StartNew();
            for (int i = 0; i < Iterations; i++)
            {
                total += Log(typeof(Test));
            }
            sw.Stop();
            Console.WriteLine("typeof(Test): {0}ms", sw.ElapsedMilliseconds);
    
            sw = Stopwatch.StartNew();
            for (int i = 0; i < Iterations; i++)
            {
                total += Log(TestType);
            }
            sw.Stop();
            Console.WriteLine("TestType (field): {0}ms", sw.ElapsedMilliseconds);
    
            Test test = new Test();
            sw = Stopwatch.StartNew();
            for (int i = 0; i < Iterations; i++)
            {
                total += Log(test.GetType());
            }
            sw.Stop();
            Console.WriteLine("test.GetType(): {0}ms", sw.ElapsedMilliseconds);
        }
    
        // I suspect your real Log method won't be inlined,
        // so let's mimic that here
        [MethodImpl(MethodImplOptions.NoInlining)]
        static int Log(Type type)
        {
            return 1;
        }
    }
    

提交回复
热议问题