Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using properties and performance

I was optimizing my code, and I noticed that using properties (even auto properties) has a profound impact on the execution time. See the example below:

[Test]
public void GetterVsField()
{
    PropertyTest propertyTest = new PropertyTest();
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();
    propertyTest.LoopUsingCopy();
    Console.WriteLine("Using copy: " + stopwatch.ElapsedMilliseconds / 1000.0);

    stopwatch.Restart();
    propertyTest.LoopUsingGetter();
    Console.WriteLine("Using getter: " + stopwatch.ElapsedMilliseconds / 1000.0);
    stopwatch.Restart();
    propertyTest.LoopUsingField();
    Console.WriteLine("Using field: " + stopwatch.ElapsedMilliseconds / 1000.0);
}

public class PropertyTest
{
    public PropertyTest()
    {
        NumRepet = 100000000;
        _numRepet = NumRepet;
    }

    int NumRepet { get; set; }
    private int _numRepet;
    public int LoopUsingGetter()
    {
        int dummy = 314;
        for (int i = 0; i < NumRepet; i++)
        {
            dummy++;
        }
        return dummy;
    }

    public int LoopUsingCopy()
    {
        int numRepetCopy = NumRepet;
        int dummy = 314;
        for (int i = 0; i < numRepetCopy; i++)
        {
            dummy++;
        }
        return dummy;
    }

    public int LoopUsingField()
    {
        int dummy = 314;
        for (int i = 0; i < _numRepet; i++)
        {
            dummy++;
        }
        return dummy;
    }
}

In Release mode on my machine I get:

Using copy: 0.029
Using getter: 0.054
Using field: 0.026 

which in my case is a disaster - the most critical loop just can't use any properties if I want to get maximum performance.

What am I doing wrong here? I was thinking that these would be inlined by the JIT optimizer.

like image 910
Grzenio Avatar asked Mar 07 '14 09:03

Grzenio


People also ask

What are the benefits of using properties?

The main advantage of properties is that they allow us to encapsulate our data inside our class in such a way that we can control access to our class's data through only the properties and not by allowing outside programs to access our fields directly.

What are the uses of properties?

Why We Use Properties: Properties allow you to change a single object and it will have an isolated effect on your program, independent of other objects. Properties are what make objects different from each other.

Why we use properties instead of public variables?

Property always a better choice instead of public variables. Property is safe while public variables are unsafe. And you can not debug with public variables but you can do that with property. Public variables are useful.


Video Answer


1 Answers

Getters/Setters are syntactic sugar for methods with a few special conventions ("value" variable in a setter", and no visible parameter list).

According to this article, "If any of the method's formal arguments are structs, the method will not be inlined." -- ints are structs. Therefore, I think this limitation applies.

I haven't looked at the IL produced by the following code, but I did get some interesting results that I think shows this working this way...

using System;
using System.Diagnostics;

public static class Program{
public static void Main()
{
    PropertyTest propertyTest = new PropertyTest();
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();
    propertyTest.LoopUsingField();
    Console.WriteLine("Using field: " + stopwatch.ElapsedMilliseconds / 1000.0);


    stopwatch.Restart();
    propertyTest.LoopUsingBoxedGetter();
    Console.WriteLine("Using boxed getter: " + stopwatch.ElapsedMilliseconds / 1000.0);

    stopwatch.Restart();
    propertyTest.LoopUsingUnboxedGetter();
    Console.WriteLine("Using unboxed getter: " + stopwatch.ElapsedMilliseconds / 1000.0);

}

}
public class PropertyTest
{
    public PropertyTest()
    {
        _numRepeat = 1000000000L;
        _field = 1;
        Property = 1;
        IntProperty = 1;
    }

    private long _numRepeat;
    private object _field = null;
    private object Property {get;set;}
    private int IntProperty {get;set;}

    public void LoopUsingBoxedGetter()
    {

        for (long i = 0; i < _numRepeat; i++)
        {
          var f = Property;
        }

    }

    public void LoopUsingUnboxedGetter()
    {
        for (long i = 0; i < _numRepeat; i++)
        {
            var f = IntProperty;
        }
    }

    public void LoopUsingField()
    {
        for (long i = 0; i < _numRepeat; i++)
        {
            var f = _field;
        }
    }
}

This produces.. ON MY MACHINE, OS X (recent version of Mono), these results (in seconds):

  • Using field: 2.606
  • Using boxed getter: 2.585
  • Using unboxed getter: 2.71
like image 170
Andrew Theken Avatar answered Oct 08 '22 21:10

Andrew Theken