4

I'm often confused by this. I've always been taught to name numbers I use often using variables or constants, but if it reduces the efficiency of the program, should I still do it? Heres an example:

private int CenterText(Font font, PrintPageEventArgs e, string text)
    {
        int recieptCenter = 125;
        int stringLength = Convert.ToInt32(e.Graphics.MeasureString(text, font));
        return recieptCenter - stringLength / 2;
    }

The above code is using named variables, but runs slower then this code:

private int CenterText(Font font, PrintPageEventArgs e, string text)
    {
        return 125 - Convert.ToInt32(e.Graphics.MeasureString(text, font) / 2);
    }

In this example, the difference in execution time is minimal, but what about in larger blocks of code?

Jonathan Nixon
  • 4,940
  • 5
  • 39
  • 53
Nathan
  • 1,287
  • 6
  • 15
  • 32
  • Posted the same method twice, and then forgot to divide length by 2. Question is correct now. – Nathan Oct 18 '13 at 19:00
  • 1
    There is a subjective grey area between "readability" and "conciseness"........ opinions will vary. – granadaCoder Oct 18 '13 at 19:01
  • 1
    I prefer the first, because 6 months from now, somebody might be able to figure out what I did. But I would defined "const" values for the 125 and the 2............... so the values mean something...not just some random int hanging in there. – granadaCoder Oct 18 '13 at 19:02
  • 1
    A performance difference like that is the least of your worries. Also, I'm sure this measured in the debugger which means your benchmarks aren't accurate. Also, I'm sure a `const` will perform the same as a hard coded value. – Dave Zych Oct 18 '13 at 19:02
  • This will be closed for being an opinionated answer. That being said: readability is more important when the difference is so incredibly small. The compiler will optimize most of this anyway, but it will take another programmer a lot more time to understand it. – Jeroen Vannevel Oct 18 '13 at 19:02
  • 1
    1) Even if there is a difference, I find it very, very, very unlikely that it's enough of a difference to be a real problem in your application that makes the difference between one that is too slow and one that is fast enough. 2) How did you measure the difference? Odds are, you ran into one of many common benchmarking pitfalls. Benchmarking microoptimizations is *very* hard. – Servy Oct 18 '13 at 19:02
  • Normaly you should use a variable. If someone has to work with your code no one knows why there is a certain number in your code. You will forget this, too. – user1567896 Oct 18 '13 at 19:03
  • 1
    You are allowed to add comments to the code too, so when someone else looks at the code they can understand it better than try to "read" the code. "const" values are really just being added as hard coded values during compile, but helpful if the same value is to be used multiple places. – Quintium Oct 18 '13 at 19:06
  • 2
    Are you aware that the two methods are _slightly_ different? The first one converts the measurement to an integer, _then_ divides in half. The second method divides the measurement in half _then_ converts to an integer. I wonder if this is causing your measureable difference (though I suspect it's a typo). I'm honestly surprised it is; to me, I would expect that the runtime jitted code (assuming its running in release mode without an attached debugger) would be nearly identical. I see nothing there in the first example that the compiler could not optimize anyway to produce the second example. – Chris Sinclair Oct 18 '13 at 19:12

3 Answers3

9

The difference between using variables and hard-coded values is going to be negligible at worst. Compilers deal with things like this quite well. If you saw a difference in performance I would like to hear about your methodology for collecting those metrics. (Your test itself may be suspect and most likely not repeatable.)

In any case, you should first worry about making your program correct and maintainable. That means:

  • Carefully naming your classes, methods and variables
  • Separating concerns
  • Avoiding magic numbers and strings (What the heck is 125 and what does it mean?)
  • Avoid harcoding
  • etc.

Also, receiptCenter does not sound like it should even be a constant. It may change infrequently but I would suggest that you store it outside of your app in a config file, or db table etc. If that value ever needs to change you have to recompile and push the whole thing to prod. Also, what about publishing your software in some other place where the value of receiptCenter is different? You just want to change a config setting, not build a different version of the app just for that instance.

Optimization is the last thing you worry about, unless it's the first thing you have to worry about and that's an architect/expert-level consideration.

Paul Sasik
  • 79,492
  • 20
  • 149
  • 189
  • I can't see any premature optimization in the question. The rest is surely true. PS: Typo in hardoding (lacks a "c"). – JensG Oct 18 '13 at 19:16
  • @JensG: Thanks for the heads up on the typo. For premature opt. Please re-read the OP's title carefully: `Performance implications of using a variable versus a magic number` That's the very definition of premature optimization, and a very n00b one at that. Please also see my edit. – Paul Sasik Oct 18 '13 at 19:19
  • Ok, agree. Now I see it :-) – JensG Oct 18 '13 at 19:22
  • @PaulSasik To be fair, the original question title was different (and entirely undescriptive) so I edited it. That's title was written by me, not the OP. – Servy Oct 18 '13 at 19:27
  • @Servy: Good to know, but the OP does echo worries about performance in the very first sentence with: `but if it reduces the efficiency of the program`. So even with a title change I think the prem. op. idea and critique holds. Also, this seemingly simple question must be a tip-of-the-iceberg of software design problems... Just discussing the defining of a constant named `receiptCenter` sends up red flags for me. Yes, I am assuming a certain set of semantics based on the name, and if the variable was actually named well, then they are correct and the value should come from a config file. – Paul Sasik Oct 18 '13 at 19:33
  • @PaulSasik I agree it seems to be a main concern of his, which is why I felt comfortable using the title I did. I just wanted you to be aware that it wasn't the OP's words, and that it shouldn't be the sole basis for interpreting his intentions. – Servy Oct 18 '13 at 19:34
  • @Servy: No problem, good edit. And if you read my latest edit you'll see that I'm ranting on about a lot more besides premature optimization. There seem to be a number of different considerations that the OP isn't making, or is taking the wrong ones into account. – Paul Sasik Oct 18 '13 at 19:37
9

When they say "use constants" they literally mean "use constants"; they do not mean "use variables that never change".

This is equivalent to your code:

const int recieptCenter = 125;
int stringLength = Convert.ToInt32(e.Graphics.MeasureString(text, font));
return recieptCenter - stringLength / 2;

With the const keyword in place, the compiler knows that 125 will never change, and will be able to apply the optimizations that it would apply to a constant expressed as a literal.

There is a huge advantage to naming your "magic numbers": people who maintain your code after you leave the company would know what's the meaning of 125. It will help you, too, when you come back to revisit this code in a few years.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 2
    `It will help you, too, when you come back to revisit this code in a few years.` - Or even a few weeks. – Dave Zych Oct 18 '13 at 19:46
-1

receiptCenter should be a constant declared somewhere outside that private method, in some obvious place, where all your constants are declared together. Alternatively, it could be a variable read from configuration.

It really does not improve your code when you give a name to a constant number somewhere in a private method deep inside of your class library.

JustAndrei
  • 863
  • 4
  • 17
  • 1
    What would it add to understandig of the meaning of the variables if they are declared in a single place? If the constant is only used in one method, why tear declaration and usage apart? Why read the value of pi from configuration? A constant does improve the code, even when it's declard in the same method, because it adds clarity to the meaning of the number. – Markus Meyer Oct 18 '13 at 19:13
  • 1
    One example is configuration. Even if you use that constant just once, you still may need an option to change it later. If the number is read from a configuration file or database, it certainly will make your life easier. – JustAndrei Oct 18 '13 at 19:19
  • +1 for the consideration that this is better read from config. I doubt this variable qualifies for true constant semantics like Math.PI. Also, @MarkusMeyer: to see a grouping of constants point your favorite decompiler at the System.Math class in .NET to see what Justandrei is talking about. – Paul Sasik Oct 18 '13 at 19:42