Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Field vs Property. Optimisation of performance

Please note this question related to performance only. Lets skip design guidelines, philosophy, compatibility, portability and anything what is not related to pure performance. Thank you.

Now to the question. I always assumed that because C# getters/setters are really methods in disguise then reading public field must be faster than calling a getter.

So to make sure I did a test (the code below). However this test only produces expected results (ie fields are faster than getters at 34%) if you run it from inside Visual Studio.

Once you run it from command line it shows pretty much the same timing...

The only explanation could be is that the CLR does additional optimisation (correct me if I am wrong here).

I do not believe that in real application where those properties being used in much more sophisticated way they will be optimised in the same way.

Please help me to prove or disprove the idea that in real life properties are slower than fields.

The question is - how should I modify the test classes to make the CLR change behaviour so the public field outperfroms the getters. OR show me that any property without internal logic will perform the same as a field (at least on the getter)

EDIT: I am only talking about Release x64 build.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace PropertyVsField
{
    class Program
    {
        static int LEN = 20000000;
        static void Main(string[] args)
        {
            List<A> a = new List<A>(LEN);
            List<B> b = new List<B>(LEN);

            Random r = new Random(DateTime.Now.Millisecond);

            for (int i = 0; i < LEN; i++)
            {
                double p = r.NextDouble();
                a.Add(new A() { P = p });
                b.Add(new B() { P = p });
            }

            Stopwatch sw = new Stopwatch();

            double d = 0.0;

            sw.Restart();
            for (int i = 0; i < LEN; i++)
            {
                d += a[i].P;
            }

            sw.Stop();

            Console.WriteLine("auto getter. {0}. {1}.", sw.ElapsedTicks, d);

            sw.Restart();
            for (int i = 0; i < LEN; i++)
            {
                d += b[i].P;
            }

            sw.Stop();

            Console.WriteLine("      field. {0}. {1}.", sw.ElapsedTicks, d);

            Console.ReadLine();
        }
    }

    class A
    {
        public double P { get; set; }
    }
    class B
    {
        public double P;
    }
}
like image 805
Boppity Bop Avatar asked Mar 23 '12 16:03

Boppity Bop


3 Answers

As others have already mentioned, the getters are inlined.

If you want to avoid inlining, you have to

  • replace the automatic properties with manual ones:

    class A 
    {
        private double p;
        public double P
        {
            get { return p; }
            set { p = value; }
        }
    } 
    
  • and tell the compiler not to inline the getter (or both, if you feel like it):

            [MethodImpl(MethodImplOptions.NoInlining)]
            get { return p; }
    

Note that the first change does not make a difference in performance, whereas the second change shows a clear method call overhead:

Manual properties:

auto getter. 519005. 10000971,0237547.
      field. 514235. 20001942,0475098.

No inlining of the getter:

auto getter. 785997. 10000476,0385552.
      field. 531552. 20000952,077111.
like image 82
Heinzi Avatar answered Nov 15 '22 01:11

Heinzi


Have a look at the Properties vs Fields – Why Does it Matter? (Jonathan Aneja) blog article from one of the VB team members on MSDN. He outlines the property versus fields argument and also explains trivial properties as follows:

One argument I’ve heard for using fields over properties is that “fields are faster”, but for trivial properties that’s actually not true, as the CLR’s Just-In-Time (JIT) compiler will inline the property access and generate code that’s as efficient as accessing a field directly.

like image 30
JamieSee Avatar answered Nov 15 '22 00:11

JamieSee


The JIT will inline any method (not just a getter) that its internal metrics determine will be faster inlined. Given that a standard property is return _Property; it will be inlined in every case.

The reason you are seeing different behavior is that in Debug mode with a debugger attached, the JIT is significantly handicapped, to ensure that any stack locations match what you would expect from the code.

You are also forgetting the number one rule of performance, testing beats thinking. For instance even though quick sort is asymptotically faster than insertion sort, insertion sort is actually faster for extremely small inputs.

like image 13
Guvante Avatar answered Nov 15 '22 01:11

Guvante