Accessing Properties Faster than Accessing Fields?

Hello all,

I was doing some simple performance test to determine just how much slower properties are than fields in Unity, and I came across something interesting. In my test, using properties was faster than using fields! As you can see in the script posted below, I created a simple class with an integer array field (called a), and a property for that field (called A). I then tested two methods: The first was to assign the array value to another variable (called t) directly through the public field a, while the second made the assignment via the property. These test were performed in a standalone build and I got the results from the output log after playing the game. In the editor, the property access method is always about twice as slow as the public field access method.

I actually tested some other things as well, such as auto-properties, assigning the public field value to a temporary variable and then assigning that temporary variable to t, and finally using an integer rather than an integer array. All outcomes were virtually the same as the first two methods I described. That is, in repeated test of 10000 assignments/frame, the public field access method came in at about 205 ms and the property access method came in at about 175 ms.

I was under the impression that properties should be slower than fields, so why is that not the case here? Has anyone experienced similar results, or have a technical explanation to why this is happening? Thanks!

And here’s the code I used to test. I found this code online (and adjusted it slightly), it seems like it does a good job, but what do I know (I’m a noob at C#)?

using UnityEngine;
using System.Collections;
using System.Threading;
using System.Diagnostics;

public class BenchMarker : MonoBehaviour {
	
	public int iterations = 0;

	class Testing
	{
		public int[] a = new int[1];
		public int[] A
		{
			get{return a;}
			private set{a = value;}
		}
		
		public Testing(int t){A[0] = t;}
	}
	
	// Update is called once per frame
	public void Update () {
		
		Testing x = new Testing(2);

		Stopwatch stopwatch = new Stopwatch();

        Process.GetCurrentProcess().ProcessorAffinity = new System.IntPtr(2); // Uses the second Core or Processor for the Test
        Process.GetCurrentProcess().PriorityClass = 
		ProcessPriorityClass.High;  	// Prevents "Normal" processes 
				// from interrupting Threads
        Thread.CurrentThread.Priority = System.Threading.ThreadPriority.Highest;  	// Prevents "Normal" Threads 
				// from interrupting this thread
		//int a = x.A[0];
		int t;
		long avg = 0;
		UnityEngine.Debug.Log("");
	    UnityEngine.Debug.Log("");
	    UnityEngine.Debug.Log("Option 1"); 
        stopwatch.Reset();
        stopwatch.Start();
        while (stopwatch.ElapsedMilliseconds < 1200)  // A Warmup of 1000-1500 mS 
				// stabilizes the CPU cache and pipeline.
        {
            for(int i = 0; i < iterations; i++)
			{
	            t = x.a[0];
			}
        }
        stopwatch.Stop();

        for (int repeat = 0; repeat < 20; ++repeat)
        {
            stopwatch.Reset();
            stopwatch.Start();
            for(int i = 0; i < iterations; i++)
			{
				t = x.a[0];
			}
            stopwatch.Stop();
           UnityEngine.Debug.Log("Ticks: " + stopwatch.ElapsedTicks + 
			" mS: " + stopwatch.ElapsedMilliseconds);
			avg += stopwatch.ElapsedTicks;	
        }
		UnityEngine.Debug.Log("Avg = " + avg/20 + "ms");
        UnityEngine.Debug.Log(x.ToString()); // prevents optimizations (current compilers are 
		
		
		
		avg = 0;
		UnityEngine.Debug.Log("");
	    UnityEngine.Debug.Log("");
	    UnityEngine.Debug.Log("Option 2"); 
        stopwatch.Reset();
        stopwatch.Start();
        while (stopwatch.ElapsedMilliseconds < 1200)  // A Warmup of 1000-1500 mS 
				// stabilizes the CPU cache and pipeline.
        {
            for(int i = 0; i < iterations; i++)
			{
		       t = x.A[0];
			}
        }
        stopwatch.Stop();

        for (int repeat = 0; repeat < 20; ++repeat)
        {
            stopwatch.Reset();
            stopwatch.Start();
            for(int i = 0; i < iterations; i++)
			{
		        t = x.A[0];
			}
            stopwatch.Stop();
           UnityEngine.Debug.Log("Ticks: " + stopwatch.ElapsedTicks + 
			" mS: " + stopwatch.ElapsedMilliseconds);
			avg += stopwatch.ElapsedTicks;	
        }
		UnityEngine.Debug.Log("Avg = " + avg/20 + "ms");
        UnityEngine.Debug.Log(x.ToString()); // prevents optimizations (current compilers are 

		UnityEngine.Debug.Break();
	}
}

Hi Gilley,

I copied your code and ran it. I consistently got Option 1 (fields) to be about half the run time of Option 2 (properties). Typical run times were around 100ms for Option 1 and 220 ms for Option 2 with iterations set to 10000.

Fields should perform slightly better than properties, but in most cases it’s a micro-optimization. Properties have a lot of benefits over fields. Here’s a blog post talking about it. The post is specifically about VB, but it applies to C# as well.

Also, unless you look at the compiled code, it’s hard to say what kind of tricks the compiler and optimizer are pulling. Unity gave a warning: “the variable t is assigned but never used.” That would make me suspect that some or all of the code got optimized away.

Cheers!
Cahman

Did you run it via the editor or a standalone build? I’ll try using t to make sure there isn’t some optimization happening there.

Okay, I added t++ after each assignment just so t is used. Same results.

I also ran another test where I had one method assign to t from a private variable in the same class, and the other method assign to t from a public variable in the same class. Basically the same as the previous test except in the previous test, I created an object that had a public field and property; in this one the field and property are in the same class as the testing code.

The private field and property performed roughly the same, which after reading about property/method inlining, seems about right.

Hi gilley,

I ran the code from both the editor and as a standalone build. Those numbers were specifically from the standalone.

I should caution that article is specific to the Microsoft compiler. I have no idea what mono does. The point I was trying to make: there is enough stuff going on behind the scenes with the compiler, optimizer, and operating system that it isn’t always meaningful to generalize results like this. You can say that ‘this piece of code, on this computer, with this compiler, at this time of day is faster.’ But you usually can’t generalize that to ‘fields are this much faster than properties.’ If we’re dealing with a lower level language, or looking at the compiled output, then we can make more meaningful comparisons.

Cheers!
Cahman

Right, I understand that, and that’s actually one of the reasons I created this thread. I wanted to see if other people had had similar experiences with properties, to determine if my results were just peculiar to my system/methodology/etc, or if there was something Unity related that caused the properties to be faster. Because if the latter were the case, then there really would be no good reasons not to always use properties. But as your own tests shows, my results are probably particular to something on my end rather than something on Unity’s end, so problem solved!

I would never use one test that utilized one methodology to make a broad generalization! That’s just not good science ;). I was also curious, from a technical standpoint, how I would get results that indicate properties were faster than fields, as from what I’ve read, that shouldn’t happen. Anyways, thanks for your responses; at this time, my curiosity is thoroughly satisfied, so if there’s some way to close this thread, please do so Mods!