tags:

views:

344

answers:

5

Outside of the ensuring that they cannot be changed (to the tune of a compiler error), does the JIT make any optimisations for const locals?

Eg.

public static int Main(string[] args)
{
    const int timesToLoop = 50;

    for (int i=0; i<timesToLoop; i++)
    {
        // ...
    }
}
+18  A: 

The generated IL is different (using Release mode):

using constant local                   using normal local
---------------------------------------------------------------------
.entrypoint                            .entrypoint
.maxstack 2                            .maxstack 2
.locals init (                         .locals init (
    [0] int32 i)                           [0] int32 timesToLoop,
L_0000: ldc.i4.0                           [1] int32 i)
L_0001: stloc.0                        L_0000: ldc.i4.s 50 
L_0002: br.s L_0008                    L_0002: stloc.0 
L_0004: ldloc.0                        L_0003: ldc.i4.0  
L_0005: ldc.i4.1                       L_0004: stloc.1 
L_0006: add                            L_0005: br.s L_000b 
L_0007: stloc.0                        L_0007: ldloc.1 
L_0008: ldloc.0                        L_0008: ldc.i4.1 
L_0009: ldc.i4.s 50                    L_0009: add
L_000b: blt.s L_0004                   L_000a: stloc.1 
L_000d: ret                            L_000b: ldloc.1 
                                       L_000c: ldloc.0 
                                       L_000d: blt.s L_0007
                                       L_000f: ret

As you can see the compiler replaces all variable usages by the value of the constant which results in a smaller stack.

Darin Dimitrov
+1 for taking the time to check the IL!
MagicAndi
other than a insignificantly smaller stack, it's functionally the same. Interesting though.
kenny
Great answer, and nicely formatted!
Richard Szalay
A: 

Thi is not anywhere an answer, just thought it is nice to share this though the article does not mention runtime benefits explicitly:
Coding Standard Rule #2: Use const Wherever Possible

Excerpt:
Reasoning: The upside of using const as much as possible is compiler-enforced protection from unintended writes to data that should be read-only.

o.k.w
A: 

One difference is that if you had an assembly that referenced a const field in another assembly and you later changed that value, the referencing assembly would still use the old value until it was rebuilt.

GraemeF
The question refers to const locals, not const fields/members.
Richard Szalay
+2  A: 

Your code (using const) will actually be compiled as:

public static int Main(string[] args){    
for (int i=0; i < 50; i++)  
{

}
}

while a variable will compile as a variable:

public static int Main(string[] args){
int timesToLoop = 50;    
for (int i=0; i < timesToLoop; i++)  
{

}
}
stian.net
A: 

I gave the code a quick performance test, using Snippet Compiler. The code I used is as follows:

    public static void Main()
    {
        DateTime datStart = DateTime.UtcNow;
        const int timesToLoop = 1000000;

        for (int i=0; i < timesToLoop; i++)
        {
            WL("Line Number " + i.ToString());
        }

        DateTime datEnd = DateTime.UtcNow;
        TimeSpan tsTimeTaken = datEnd - datStart;
        WL("Time Taken: " + tsTimeTaken.TotalSeconds);
        RL();
    }

Note, WL and RL are simply helper methods to read and write to the console.

To test the non-constant version, I simply removed the const keyword. The results were surprising:

                        Time Taken (average of 3 runs)

Using const keyword         26.340s
Without const keyword       28.276s

I'm aware that this is very rough'n'ready test, but the use of the const keyword appears to count as a valid micro-optimization.

MagicAndi
Speaking of micro-optimisations, you should use `DateTime.UtcNow` rather than `DateTime.Now` since the former does not require a lookup of the local timezone from the OS.
Richard Szalay
Richard, Thanks, a new tip!
MagicAndi