2

Is there any performance cost for declaring a new variable in the next case:

This is an example just to demonstrate the point.

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}

And I have the next method:

Option 1:

public void MyMethod(Person person)
{
    if (person.FirstName.Contains("Ro") || (person.LastName.StartsWith("A") && person.Age > 20))
    {
        //Do something
    }
    else if (person.FirstName.Contains("Ko") || (person.LastName.StartsWith("B") && person.Age >= 40))
    {
        //Do something
    }
    else if (person.FirstName.Contains("Mo") || (person.LastName.StartsWith("C") && person.Age > 60))
    {
        //Do something
    }
    else
    {
        //Do something
    }
}

Option 2:

public void MyMethod(Person person)
{
    string firstName = person.FirstName;
    string lastName = person.LastName;
    int age = person.Age;

    if (firstName.Contains("Ro") || (lastName.StartsWith("A") && age > 20))
    {
        //Do something
    }
    else if (firstName.Contains("Ko") || (lastName.StartsWith("B") && age >= 40))
    {
        //Do something
    }
    else if (firstName.Contains("Mo") || (lastName.StartsWith("C") && age > 60))
    {
        //Do something
    }
    else
    {
        //Do something
    }
}

Again, this is just an example to demonstrate the idea of the question.

The question: Is there any performance or memory issues between option 1 and option 2?

For sure, option 2 is looking better and is more readable.

Misha Zaslavsky
  • 8,414
  • 11
  • 70
  • 116

4 Answers4

8

This is tackled by the jitter, it aggressively eliminates local variables of a method and looks for ways to store them in a CPU register instead. It does this whether or not you declare the variable yourself. Your property getters are simple and have no side-effect, something the jitter can find out by itself. Those getter methods are eliminated as well, they are inlined. In effect, it will transform your code from the 1st snippet to the second snippet.

This is the core reason that you cannot find out what local variables a method has through Reflection. And why you have a problem debugging optimized code. And why the volatile keyword exists in C#. A local variable simply doesn't exist anymore when the jitter optimizer is done with it.

You'll find an overview of the kind of optimizations performed by the jitter in this answer.

So, no, don't hesitate to make your code more readable this way, it is not expected to have any perf impact. Do keep in mind however that you can introduce a bug in your code doing this, it will trigger when the rest of your code affects the object you are using. You'll of course store a stale value of the property. This is not always that obvious if the class is non-trivial and the property getter has side-effects itself. Otherwise the core reason that coding guidelines in .NET demand that properties with side effects should be methods instead.

Community
  • 1
  • 1
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • I think you may be mistaken about the meaning of `volatile` in C#. For more information, see http://blogs.msdn.com/b/ericlippert/archive/2011/06/16/atomicity-volatility-and-immutability-are-different-part-three.aspx – Kris Vandermotten May 05 '14 at 11:19
  • 1
    I'm not. I don't think Microsoft employees will ever truly recover from having to deal with Itanium processors. On x86 it prevents the jitter from keeping a variable stored in a CPU register without refreshing it from memory. On x64 it has no effect at all. Using *volatile* to arbitrary change the memory semantics for processors with a weak memory model was a big mistake. Enough to get Joe Duffy to exclaim [volatile is evil!](http://joeduffyblog.com/2010/12/04/sayonara-volatile/) It is. – Hans Passant May 05 '14 at 11:22
  • I know that Hans. And I know you do, I just hadn't really noticed you wrote this answer. But you said "And why the volatile keyword exists in C#. Such a variable simply doesn't exist anymore when the jitter optimizer is done with it." To me that sounds as if you say that volatile variables are optimized away. That is obviously not the case. In fact, volatile (local) variables don't even exist, volatile fields do. You might consider rewording this to make sure nobody gets confused. – Kris Vandermotten May 05 '14 at 11:29
6

Meh, I find option 1 more readable. Option 2 implies that you're manipulating the values of those properties. It takes a second or two of parsing the code to figure out that you're not.

So it's just a stylistic choice. Consult your style guide to see which is preferred by your organization or particular code base.

The performance difference will be exactly nil. You probably won't trust me on this, and if not, the only way to be sure is to actually benchmark it for yourself. But that's really a waste of time.

A property getter should (unless the documentation specifies otherwise) have constant-time execution, so querying the value of the property should be no different than querying the value of a local variable. So the only other thing that could possibly impact performance is that, with option 2, you could possibly end up querying the value of all the properties, when your code might never get to the branch that requires the last name or the age. But that's probably going to be highly variable. You can really only determine this by repeated benchmarking with some real-world data. And don't waste your time unless this method is really proven to be a bottleneck. And it won't be.

If you're going to make a decision on some basis other than readability, it would be thread-safety. If the value returned by a property getter can potentially change after another thread modifies the object, then you might have a problem using Option 1. That would make caching the value of those properties into local variables more desirable, thus you'd choose Option 2.

But that is precisely why the compiler is not going to do any type of caching, turning Option 1 into Option 2, as some of the other answers suggest. The generated code will be different, the performance difference just won't be significant. (Although the JITter may certainly perform this type of optimization at run-time, as Hans points out in his answer.)

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
0

Complexity of both is same. So i think both are equal in both regards.

0

In practice there will be no difference in performance, I doubt you would be able to measure any difference even if you ran the code a billion times.

With that said, there is a difference. A property get operation is in fact a method call, so the first operation will call the person.get_FirstName method when you access the property. This means that there may, depending on how the compiler optimizes your code, be some difference in how your code behaves.

So there will not be any measurable difference and you should go for the most readable option. :-)

Rune Grimstad
  • 35,612
  • 10
  • 61
  • 76
  • I just had a similar case where the same property was used twice in a method running ~100.000/s and there WAS a measurable difference when doing a local copy to only call the getter once. – Christoph Fink May 05 '14 at 10:48
  • Was this using the default property implementation or did the property implement some actual logic? If for instance the property does a web service call then the situation is completely different. – Rune Grimstad May 05 '14 at 10:49
  • No, simple auto-properties. Time was measured using dotTrace. – Christoph Fink May 05 '14 at 10:50
  • That is interesting. The reason is probably the overhead caused by the method call that the property getter really does. – Rune Grimstad May 05 '14 at 10:56
  • @chrfin With or without optimizations enabled? – Cody Gray - on strike May 05 '14 at 10:57
  • @RuneGrimstad: Yes, according to the profiler the `get_NAME` method took the time. @CodyGray: I think it was without, but I am not sure as I did a lot of tests with both. – Christoph Fink May 05 '14 at 11:00
  • Weird. Like Hans's answer points out, the JIT compiler should certainly inline trivial property getters, *especially* when you're using auto-properties. Somehow, I'm betting you had the JITter disabled. Like running with the debugger attached, regardless of whether the code was compiled with optimization enabled. – Cody Gray - on strike May 05 '14 at 11:01
  • I don't think the JIT will always inline properties, not even auto-properties. There seems to be a heuristic behind it that determines if the property should be inlined or not. Multithreading is one possible reason not to inline it, dynamic recompilation might be another. – Rune Grimstad May 05 '14 at 11:03
  • `Multithreading is one possible reason` - this is very likely the reason in my case it was not inlined as I have multiple threads "hammering that object" at the same time... – Christoph Fink May 05 '14 at 11:07