Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assigning integers fields/properties to zero in a constructor

Tags:

c#

During a recent code review a colleague suggested that, for class with 4 int properties, assigning each to zero in the constructor would result in a performance penalty.

For example,

    public Example()
    {
        this.major = 0;
        this.minor = 0;
        this.revision = 0;
        this.build = 0;
    }

His point was that this is redundant as they will be set to zero by default and you are introducing overhead by essentially performing the same task twice. My point was that the performance hit would be negligible if one existed at all and this is more readable (there are several constructors) as the intention of the state of the object after calling this constructor is very clear.

What do you think? Is there a performance gain worth caring about here?

like image 341
Peter Kelly Avatar asked Nov 03 '10 16:11

Peter Kelly


4 Answers

No, there is not. The compiler will optimize out these operations; the same task will not be performed twice. Your colleague is wrong.

[Edit based upon input from the always-excellent Jon Skeet]

The compiler SHOULD optimize out the operations, but apparently they are not completely optimized out; however, the optimization gain is completely negligible, and the benefit from having the assignment be so explicit is good. Your colleague may not be completely wrong, but they're focusing on a completely trivial optimization.

like image 192
Paul Sonier Avatar answered Nov 15 '22 12:11

Paul Sonier


I don't believe they're the same operation, and there is a performance difference. Here's a microbenchmark to show it:

using System;
using System.Diagnostics;

class With
{
    int x;

    public With()
    {
        x = 0;
    }
}


class Without
{
    int x;

    public Without()
    {
    }
}


class Test
{
    static void Main(string[] args)
    {
        int iterations = int.Parse(args[0]);
        Stopwatch sw = Stopwatch.StartNew();
        if (args[1] == "with")
        {
            for (int i = 0; i < iterations; i++)
            {
                new With();
            }
        }
        else
        {
            for (int i = 0; i < iterations; i++)
            {
                new Without();
            }
        }
        sw.Stop();
        Console.WriteLine(sw.ElapsedMilliseconds);
    }
}

Results:

c:\Users\Jon\Test>test 1000000000 with
8427

c:\Users\Jon\Test>test 1000000000 without
881

c:\Users\Jon\Test>test 1000000000 with
7568

c:\Users\Jon\Test>test 1000000000 without
819

Now, would that make me change the code? Absolutely not. Write the most readable code first. If it's more readable with the assignment, keep the assignment there. Even though a microbenchmark shows it has a cost, that's still a small cost in the context of doing any real work. Even though the proportional difference is high, it's still creating a billion instances in 8 seconds in the "slow" route. My guess is that there's actually some sort of optimization for completely-empty constructors chaining directly to the completely empty object() constructor. The difference between assigning to two fields and only assigning to one field is much smaller.

In terms of while the compiler can't optimize it out, bear in mind that a base constructor could be modifying the value by reflection, or perhaps a virtual method call. The compiler could potentially notice those, but it seems a strange optimization.

like image 36
Jon Skeet Avatar answered Nov 15 '22 12:11

Jon Skeet


My understanding is that objects memory is cleared to zero with a simple and very fast memory wipe. these explicit assignments, however, will take additional IL. Indeed, some tools will spot you assigning the default value (in a field initialiser) and advise against it.

So I would say: don't do this - it is potentially marginally slower. But not by much. In short I think your friend is correct.

Unfortunately I'm on a mobile device right now, without the right tools to prove it.

like image 4
Marc Gravell Avatar answered Nov 15 '22 13:11

Marc Gravell


You should focus on code clarity, that is the most important thing. If performance becomes an issue, then measure performance, and see what your bottlenecks are, and improve them. It's not worth it to spend so much time worrying about performance when ease of understanding code is more important.

like image 3
McKay Avatar answered Nov 15 '22 14:11

McKay