Подтвердить что ты не робот

Есть ли время выполнения для использования константных локальных переменных?

За исключением того, что они не могут быть изменены (в зависимости от ошибки компилятора), делает ли JIT какие-либо оптимизации для locals const?

Eg.

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

    for (int i=0; i<timesToLoop; i++)
    {
        // ...
    }
}
4b9b3361

Ответ 1

Сгенерированный ИЛ отличается (с использованием режима Release):

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 

Как вы можете видеть, компилятор заменяет все переменные на значение константы, которая приводит к меньшему стеку.

Ответ 2

Я дал код быстрый тест производительности, используя Snippet Compiler. Используемый мной код выглядит следующим образом:

    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();
    }

Примечание. WL и RL - это просто вспомогательные методы для чтения и записи на консоль.

Чтобы протестировать непостоянную версию, я просто удалил ключевое слово const. Результаты были неожиданными:

                        Time Taken (average of 3 runs)

Using const keyword         26.340s
Without const keyword       28.276s

Я знаю, что это очень грубый тест, но использование ключевого слова const представляется как допустимое micro-optimization.

Ответ 3

Ваш код (используя const) будет фактически скомпилирован как:

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

    }
}

в то время как переменная будет компилироваться как переменная:

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

    }
}

Ответ 4

Это не так близко к ответу, просто подумал, что было бы неплохо поделиться этим, однако статья явно не упоминает преимущества времени исполнения:
Стандартное правило кодирования # 2: Использовать константу Где угодно

Выдержки:
Рассуждение. Потенциал использования константы как можно больше - это принудительная защита от непреднамеренных операций записи в данные, которые должны быть доступны только для чтения.

Ответ 5

Одно из отличий заключается в том, что если у вас была сборка, которая ссылалась на поле const в другой сборке, и вы позже изменили это значение, сборка ссылок все равно использовала бы старое значение, пока оно не будет восстановлено.