English 中文(简体)
Is there a runtime benefit to using const local variables?
原标题:

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++)
    {
        // ...
    }
}
最佳回答

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.

问题回答

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.

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++)  
    {

    }
}

This is not anywhere near an answer, just thought it would be nice to share this however 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.

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.





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签