Работает ли IF лучше, чем IF-ELSE? - PullRequest
65 голосов
/ 12 октября 2011

Какой из этих блоков кода работает лучше, а какой из них более читабелен? Я предполагаю, что выигрыш будет незначительным, особенно во втором блоке. Мне просто любопытно.

Блок № 1

string height;
string width;
if (myFlag == 1)
{
    height = "60%";
    width = "60%";
}
else
{
    height = "80%";
    width = "80%";
}

Блок № 2

string height = "80%";
string width = "80%";
if (myFlag == 1)
{
    height = "60%";
    width = "60%";
}
<ч />

Обновлено

Результаты при тестировании вышеуказанного кода показали, что оба блока работали одинаково

Блок № 1

myFlag = 1:   3 Milliseconds
myFlag = 0:   3 Milliseconds

Блок № 2

myFlag = 1:   3 Milliseconds
myFlag = 0:   3 Milliseconds

Но одна важная вещь, которую я заметил здесь (благодаря Мэтью Стиплз отвечает здесь ), состоит в том, что, поскольку в проверенном мной блоке кода не используются переменные height и width, за исключением присваивания в if- else и if блоки Code Block-1 и 2 соответственно, компилятор оптимизировал код IL, полностью удалив рассматриваемые блоки if и if-else, таким образом показывая здесь недопустимые результаты для нашего теста здесь .

Я обновил оба блока кода для записи значений высоты и ширины в файл, используя их снова и заставляя компилятор запускать наши тестовые блоки (я надеюсь), но вы можете наблюдать из кода что фактическая часть записи файла не влияет на результаты нашего теста

Это обновленные результаты, C # и код IL

Результаты

Блок № 1

myFlag = 1:   1688 Milliseconds
myFlag = 0:   1664 Milliseconds

Блок № 2

myFlag = 1:   1700 Milliseconds
myFlag = 0:   1677 Milliseconds

C # .net Code

Блок № 1

    public long WithIfAndElse(int myFlag)
    {
        Stopwatch myTimer = new Stopwatch();
        string someString = "";
        myTimer.Start();
        for (int i = 0; i < 1000000; i++)
        {
            string height;
            string width;
            if (myFlag == 1)
            {
                height = "60%";
                width = "60%";
            }
            else
            {
                height = "80%";
                width = "80%";
            }
            someString = "Height: " + height + Environment.NewLine + "Width: " + width;
        }
        myTimer.Stop();
        File.WriteAllText("testifelse.txt", someString);
        return myTimer.ElapsedMilliseconds;
    }

Блок № 2

    public long WithOnlyIf(int myFlag)
    {
         Stopwatch myTimer = new Stopwatch();
        string someString = "";
        myTimer.Start();
        for (int i = 0; i < 1000000; i++)
        {
            string height = "80%";
            string width = "80%";
            if (myFlag == 1)
            {
                height = "60%";
                width = "60%";
            }
            someString = "Height: " + height + Environment.NewLine + "Width: " + width;
        }
        myTimer.Stop();
        File.WriteAllText("testif.txt", someString);
        return myTimer.ElapsedMilliseconds;
    }

Код IL, сгенерированный ildasm.exe

Блок № 1

.method public hidebysig instance int64  WithIfAndElse(int32 myFlag) cil managed
{
  // Code size       144 (0x90)
  .maxstack  3
  .locals init ([0] class [System]System.Diagnostics.Stopwatch myTimer,
           [1] string someString,
           [2] int32 i,
           [3] string height,
           [4] string width,
           [5] string[] CS$0$0000)
  IL_0000:  newobj     instance void [System]System.Diagnostics.Stopwatch::.ctor()
  IL_0005:  stloc.0
  IL_0006:  ldstr      ""
  IL_000b:  stloc.1
  IL_000c:  ldloc.0
  IL_000d:  callvirt   instance void [System]System.Diagnostics.Stopwatch::Start()
  IL_0012:  ldc.i4.0
  IL_0013:  stloc.2
  IL_0014:  br.s       IL_0070
  IL_0016:  ldarg.1
  IL_0017:  ldc.i4.1
  IL_0018:  bne.un.s   IL_0029
  IL_001a:  ldstr      "60%"
  IL_001f:  stloc.3
  IL_0020:  ldstr      "60%"
  IL_0025:  stloc.s    width
  IL_0027:  br.s       IL_0036
  IL_0029:  ldstr      "80%"
  IL_002e:  stloc.3
  IL_002f:  ldstr      "80%"
  IL_0034:  stloc.s    width
  IL_0036:  ldc.i4.5
  IL_0037:  newarr     [mscorlib]System.String
  IL_003c:  stloc.s    CS$0$0000
  IL_003e:  ldloc.s    CS$0$0000
  IL_0040:  ldc.i4.0
  IL_0041:  ldstr      "Height: "
  IL_0046:  stelem.ref
  IL_0047:  ldloc.s    CS$0$0000
  IL_0049:  ldc.i4.1
  IL_004a:  ldloc.3
  IL_004b:  stelem.ref
  IL_004c:  ldloc.s    CS$0$0000
  IL_004e:  ldc.i4.2
  IL_004f:  call       string [mscorlib]System.Environment::get_NewLine()
  IL_0054:  stelem.ref
  IL_0055:  ldloc.s    CS$0$0000
  IL_0057:  ldc.i4.3
  IL_0058:  ldstr      "Width: "
  IL_005d:  stelem.ref
  IL_005e:  ldloc.s    CS$0$0000
  IL_0060:  ldc.i4.4
  IL_0061:  ldloc.s    width
  IL_0063:  stelem.ref
  IL_0064:  ldloc.s    CS$0$0000
  IL_0066:  call       string [mscorlib]System.String::Concat(string[])
  IL_006b:  stloc.1
  IL_006c:  ldloc.2
  IL_006d:  ldc.i4.1
  IL_006e:  add
  IL_006f:  stloc.2
  IL_0070:  ldloc.2
  IL_0071:  ldc.i4     0xf4240
  IL_0076:  blt.s      IL_0016
  IL_0078:  ldloc.0
  IL_0079:  callvirt   instance void [System]System.Diagnostics.Stopwatch::Stop()
  IL_007e:  ldstr      "testifelse.txt"
  IL_0083:  ldloc.1
  IL_0084:  call       void [mscorlib]System.IO.File::WriteAllText(string,
                                                                   string)
  IL_0089:  ldloc.0
  IL_008a:  callvirt   instance int64 [System]System.Diagnostics.Stopwatch::get_ElapsedMilliseconds()
  IL_008f:  ret
} // end of method frmResearch::WithIfAndElse

Блок № 2

.method public hidebysig instance int64  WithOnlyIf(int32 myFlag) cil managed
{
  // Code size       142 (0x8e)
  .maxstack  3
  .locals init ([0] class [System]System.Diagnostics.Stopwatch myTimer,
           [1] string someString,
           [2] int32 i,
           [3] string height,
           [4] string width,
           [5] string[] CS$0$0000)
  IL_0000:  newobj     instance void [System]System.Diagnostics.Stopwatch::.ctor()
  IL_0005:  stloc.0
  IL_0006:  ldstr      ""
  IL_000b:  stloc.1
  IL_000c:  ldloc.0
  IL_000d:  callvirt   instance void [System]System.Diagnostics.Stopwatch::Start()
  IL_0012:  ldc.i4.0
  IL_0013:  stloc.2
  IL_0014:  br.s       IL_006e
  IL_0016:  ldstr      "80%"
  IL_001b:  stloc.3
  IL_001c:  ldstr      "80%"
  IL_0021:  stloc.s    width
  IL_0023:  ldarg.1
  IL_0024:  ldc.i4.1
  IL_0025:  bne.un.s   IL_0034
  IL_0027:  ldstr      "60%"
  IL_002c:  stloc.3
  IL_002d:  ldstr      "60%"
  IL_0032:  stloc.s    width
  IL_0034:  ldc.i4.5
  IL_0035:  newarr     [mscorlib]System.String
  IL_003a:  stloc.s    CS$0$0000
  IL_003c:  ldloc.s    CS$0$0000
  IL_003e:  ldc.i4.0
  IL_003f:  ldstr      "Height: "
  IL_0044:  stelem.ref
  IL_0045:  ldloc.s    CS$0$0000
  IL_0047:  ldc.i4.1
  IL_0048:  ldloc.3
  IL_0049:  stelem.ref
  IL_004a:  ldloc.s    CS$0$0000
  IL_004c:  ldc.i4.2
  IL_004d:  call       string [mscorlib]System.Environment::get_NewLine()
  IL_0052:  stelem.ref
  IL_0053:  ldloc.s    CS$0$0000
  IL_0055:  ldc.i4.3
  IL_0056:  ldstr      "Width: "
  IL_005b:  stelem.ref
  IL_005c:  ldloc.s    CS$0$0000
  IL_005e:  ldc.i4.4
  IL_005f:  ldloc.s    width
  IL_0061:  stelem.ref
  IL_0062:  ldloc.s    CS$0$0000
  IL_0064:  call       string [mscorlib]System.String::Concat(string[])
  IL_0069:  stloc.1
  IL_006a:  ldloc.2
  IL_006b:  ldc.i4.1
  IL_006c:  add
  IL_006d:  stloc.2
  IL_006e:  ldloc.2
  IL_006f:  ldc.i4     0xf4240
  IL_0074:  blt.s      IL_0016
  IL_0076:  ldloc.0
  IL_0077:  callvirt   instance void [System]System.Diagnostics.Stopwatch::Stop()
  IL_007c:  ldstr      "testif.txt"
  IL_0081:  ldloc.1
  IL_0082:  call       void [mscorlib]System.IO.File::WriteAllText(string,
                                                                   string)
  IL_0087:  ldloc.0
  IL_0088:  callvirt   instance int64 [System]System.Diagnostics.Stopwatch::get_ElapsedMilliseconds()
  IL_008d:  ret
} // end of method frmResearch::WithOnlyIf

Таким образом, мы можем сказать, что блок IF-Else (Блок № 1) работает быстрее, чем блок if (Блок № 2) , как указано многими на этом форуме.

Ответы [ 12 ]

93 голосов
/ 12 октября 2011

Результаты испытаний

10 000 000 итераций Блок 1

myFlag = 0:    23.8ns per iteration
myFlag = 1:    23.8ns per iteration

10 000 000 итераций Блок 2

myFlag = 0:    23.8ns per iteration
myFlag = 1:    46.8ns per iteration

Блок 2 на 96% медленнее, чем Блок 1 .Имеет смысл, так как Блок 2 выполняет вдвое большую работу в пессимистическом случае.

Я предпочитаю любой случай, в зависимости от ситуации.Если myFlag равен , редко когда 1, то он хочет, чтобы он выделялся как крайний случай, с которым мы должны работать.Если оба одинаково вероятны, я хочу синтаксис if-else.Но это предпочтение, а не факт.


Несколько десятилетий назад двойной конвейер intel 80286 остановился бы, если бы был выполнен условный переход, вместо того, чтобы перейти к следующей инструкции.Ко времени Pentium, который ушел;ЦП предварительно выбирает оба пути ветвления.Но в глубине души я все еще испытываю приступ страха, когда пишу код, который имеет наиболее распространенный результат в предложении else.Каждый раз я должен напоминать себе, что это больше не имеет значения.


Int32 reps = 10000000;

private void Block1(int myFlag)
{
    String width;
    String height;

    Stopwatch sw = new Stopwatch();
    sw.Start();
    for (int i = 0; i < reps; i++)
    {
        if (myFlag == 1)
        {
            width = String.Format("{0:g}%", 60);
            height = String.Format("{0:g}%", 60);
        }
        else
        {
            width = String.Format("{0:g}%", 80);
            height = String.Format("{0:g}%", 80);
        }
    }
    sw.Stop();
    Double time = (Double)sw.Elapsed.Ticks / Stopwatch.Frequency * 1000000000.0 / reps;
    MessageBox.Show(time.ToString() + " ns");
}

private void Block2(int myFlag)
{
    String width;
    String height;

    Stopwatch sw = new Stopwatch();
    sw.Start();
    for (int i = 0; i < reps; i++)
    {
        width = String.Format("{0:g}%", 80);
        height = String.Format("{0:g}%", 80);
        if (myFlag == 1)
        {
            width = String.Format("{0:g}%", 60);
            height = String.Format("{0:g}%", 60);
        }
    }
    sw.Stop();

    Double time = (Double)sw.Elapsed.Ticks / Stopwatch.Frequency * 1000000000.0 / reps;
    MessageBox.Show(time.ToString() + " ns");
}
  • String.Format замедляет IF 96%
  • GetPercentageString(0.60) делаетIF 96% медленнее

const
   reps = 10000000;

procedure Block1(myflag: Integer);
var
   width, height: string;
   i: Integer;
   t1, t2: Int64;
   time: Extended;
   freq: Int64;
begin
   QueryPerformanceCounter(t1);
   for i := 1 to reps do
   begin
      if myFlag = 1 then
      begin
         width := '60%';
         height := '60%';
      end
      else
      begin
         width := '80%';
         height := '80%';
      end;
   end;
   QueryPerformanceCounter(t2);
   QueryPerformanceFrequency(freq);

   time := (t2-t1) / freq * 1000000000 / reps;
   ShowMessage(FloatToStr(time)+ 'ns');
end;

procedure Block2(myflag: Integer);
var
   width, height: string;
   i: Integer;
   t1, t2: Int64;
   time: Extended;
   freq: Int64;
begin
   QueryPerformanceCounter(t1);
   for i := 1 to reps do
   begin
      width := '80%';
      height := '80%';
      if myFlag = 1 then
      begin
         width := '60%';
         height := '60%';
      end;
   end;
   QueryPerformanceCounter(t2);
   QueryPerformanceFrequency(freq);

   time := (t2-t1) / freq * 1000000000 / reps;
   ShowMessage(FloatToStr(time)+ 'ns');
end;

Выполнение вдвое большего объема работы занимает примерно вдвое больше времени.

Ответ: ЕСЛИ не выполняетсялучше, чем IF-ELSE.


enter image description here

45 голосов
/ 12 октября 2011

Прирост производительности здесь незначителен для мелодии, которую я бы назвал этой микро-микро-микро-оптимизацией.Пойдите для удобочитаемости здесь, если вы не планируете сделать это пару миллионов раз.

Редактировать: (re: вопрос в комментариях)

По-моему, первыйболее читабельным.Он явно показывает в готовом формате, какие строки должны быть для каждого случая.Во втором случае регистр отсутствует, поэтому рецензент должен будет просмотреть другие области кода, чтобы определить значение по умолчанию.Чтобы представить это в перспективе, представьте 50 строк кода между исходным объявлением / инициализацией и этим конкретным блоком кода.Если в этом случае станет неясно, тогда это решит для меня.

13 голосов
/ 13 октября 2011

Обновлено

После обновления кода в соответствии с Ответ Мэтью Стипла и тестирование кода в сборке выпуска в соответствии с Лу Франко , яобнаружил, что if-Else blcoks работает лучше, чем блок if, хотя незначительно

В моем тестовом приложении я использовал следующие кодовые блоки

C # .net Code

Блок № 1

    public long WithIfAndElse(int myFlag)
    {
        Stopwatch myTimer = new Stopwatch();
        string someString = "";
        myTimer.Start();
        for (int i = 0; i < 1000000; i++)
        {
            string height;
            string width;
            if (myFlag == 1)
            {
                height = "60%";
                width = "60%";
            }
            else
            {
                height = "80%";
                width = "80%";
            }
            someString = "Height: " + height + Environment.NewLine + "Width: " + width;
        }
        myTimer.Stop();
        File.WriteAllText("testifelse.txt", someString);
        return myTimer.ElapsedMilliseconds;
    }

Блок № 2

    public long WithOnlyIf(int myFlag)
    {
        Stopwatch myTimer = new Stopwatch();
        string someString = "";
        myTimer.Start();
        for (int i = 0; i < 1000000; i++)
        {
            string height = "80%";
            string width = "80%";
            if (myFlag == 1)
            {
                height = "60%";
                width = "60%";
            }
            someString = "Height: " + height + Environment.NewLine + "Width: " + width;
        }
        myTimer.Stop();
        File.WriteAllText("testif.txt", someString);
        return myTimer.ElapsedMilliseconds;
    }

Ниже приведены результаты для сборки выпуска

Результаты для 1000000 итераций

Блок № 1

myFlag = 1:   1688 Milliseconds
myFlag = 0:   1664 Milliseconds

Блок № 2

myFlag = 1:   1700 Milliseconds
myFlag = 0:   1677 Milliseconds

IL-код, сгенерированный ildasm.exe

Блок № 1

.method public hidebysig instance int64  WithIfAndElse(int32 myFlag) cil managed
{
  // Code size       144 (0x90)
  .maxstack  3
  .locals init ([0] class [System]System.Diagnostics.Stopwatch myTimer,
           [1] string someString,
           [2] int32 i,
           [3] string height,
           [4] string width,
           [5] string[] CS$0$0000)
  IL_0000:  newobj     instance void [System]System.Diagnostics.Stopwatch::.ctor()
  IL_0005:  stloc.0
  IL_0006:  ldstr      ""
  IL_000b:  stloc.1
  IL_000c:  ldloc.0
  IL_000d:  callvirt   instance void [System]System.Diagnostics.Stopwatch::Start()
  IL_0012:  ldc.i4.0
  IL_0013:  stloc.2
  IL_0014:  br.s       IL_0070
  IL_0016:  ldarg.1
  IL_0017:  ldc.i4.1
  IL_0018:  bne.un.s   IL_0029
  IL_001a:  ldstr      "60%"
  IL_001f:  stloc.3
  IL_0020:  ldstr      "60%"
  IL_0025:  stloc.s    width
  IL_0027:  br.s       IL_0036
  IL_0029:  ldstr      "80%"
  IL_002e:  stloc.3
  IL_002f:  ldstr      "80%"
  IL_0034:  stloc.s    width
  IL_0036:  ldc.i4.5
  IL_0037:  newarr     [mscorlib]System.String
  IL_003c:  stloc.s    CS$0$0000
  IL_003e:  ldloc.s    CS$0$0000
  IL_0040:  ldc.i4.0
  IL_0041:  ldstr      "Height: "
  IL_0046:  stelem.ref
  IL_0047:  ldloc.s    CS$0$0000
  IL_0049:  ldc.i4.1
  IL_004a:  ldloc.3
  IL_004b:  stelem.ref
  IL_004c:  ldloc.s    CS$0$0000
  IL_004e:  ldc.i4.2
  IL_004f:  call       string [mscorlib]System.Environment::get_NewLine()
  IL_0054:  stelem.ref
  IL_0055:  ldloc.s    CS$0$0000
  IL_0057:  ldc.i4.3
  IL_0058:  ldstr      "Width: "
  IL_005d:  stelem.ref
  IL_005e:  ldloc.s    CS$0$0000
  IL_0060:  ldc.i4.4
  IL_0061:  ldloc.s    width
  IL_0063:  stelem.ref
  IL_0064:  ldloc.s    CS$0$0000
  IL_0066:  call       string [mscorlib]System.String::Concat(string[])
  IL_006b:  stloc.1
  IL_006c:  ldloc.2
  IL_006d:  ldc.i4.1
  IL_006e:  add
  IL_006f:  stloc.2
  IL_0070:  ldloc.2
  IL_0071:  ldc.i4     0xf4240
  IL_0076:  blt.s      IL_0016
  IL_0078:  ldloc.0
  IL_0079:  callvirt   instance void [System]System.Diagnostics.Stopwatch::Stop()
  IL_007e:  ldstr      "testifelse.txt"
  IL_0083:  ldloc.1
  IL_0084:  call       void [mscorlib]System.IO.File::WriteAllText(string,
                                                                   string)
  IL_0089:  ldloc.0
  IL_008a:  callvirt   instance int64 [System]System.Diagnostics.Stopwatch::get_ElapsedMilliseconds()
  IL_008f:  ret
} // end of method frmResearch::WithIfAndElse

Блок № 2

.method public hidebysig instance int64  WithOnlyIf(int32 myFlag) cil managed
{
  // Code size       142 (0x8e)
  .maxstack  3
  .locals init ([0] class [System]System.Diagnostics.Stopwatch myTimer,
           [1] string someString,
           [2] int32 i,
           [3] string height,
           [4] string width,
           [5] string[] CS$0$0000)
  IL_0000:  newobj     instance void [System]System.Diagnostics.Stopwatch::.ctor()
  IL_0005:  stloc.0
  IL_0006:  ldstr      ""
  IL_000b:  stloc.1
  IL_000c:  ldloc.0
  IL_000d:  callvirt   instance void [System]System.Diagnostics.Stopwatch::Start()
  IL_0012:  ldc.i4.0
  IL_0013:  stloc.2
  IL_0014:  br.s       IL_006e
  IL_0016:  ldstr      "80%"
  IL_001b:  stloc.3
  IL_001c:  ldstr      "80%"
  IL_0021:  stloc.s    width
  IL_0023:  ldarg.1
  IL_0024:  ldc.i4.1
  IL_0025:  bne.un.s   IL_0034
  IL_0027:  ldstr      "60%"
  IL_002c:  stloc.3
  IL_002d:  ldstr      "60%"
  IL_0032:  stloc.s    width
  IL_0034:  ldc.i4.5
  IL_0035:  newarr     [mscorlib]System.String
  IL_003a:  stloc.s    CS$0$0000
  IL_003c:  ldloc.s    CS$0$0000
  IL_003e:  ldc.i4.0
  IL_003f:  ldstr      "Height: "
  IL_0044:  stelem.ref
  IL_0045:  ldloc.s    CS$0$0000
  IL_0047:  ldc.i4.1
  IL_0048:  ldloc.3
  IL_0049:  stelem.ref
  IL_004a:  ldloc.s    CS$0$0000
  IL_004c:  ldc.i4.2
  IL_004d:  call       string [mscorlib]System.Environment::get_NewLine()
  IL_0052:  stelem.ref
  IL_0053:  ldloc.s    CS$0$0000
  IL_0055:  ldc.i4.3
  IL_0056:  ldstr      "Width: "
  IL_005b:  stelem.ref
  IL_005c:  ldloc.s    CS$0$0000
  IL_005e:  ldc.i4.4
  IL_005f:  ldloc.s    width
  IL_0061:  stelem.ref
  IL_0062:  ldloc.s    CS$0$0000
  IL_0064:  call       string [mscorlib]System.String::Concat(string[])
  IL_0069:  stloc.1
  IL_006a:  ldloc.2
  IL_006b:  ldc.i4.1
  IL_006c:  add
  IL_006d:  stloc.2
  IL_006e:  ldloc.2
  IL_006f:  ldc.i4     0xf4240
  IL_0074:  blt.s      IL_0016
  IL_0076:  ldloc.0
  IL_0077:  callvirt   instance void [System]System.Diagnostics.Stopwatch::Stop()
  IL_007c:  ldstr      "testif.txt"
  IL_0081:  ldloc.1
  IL_0082:  call       void [mscorlib]System.IO.File::WriteAllText(string,
                                                                   string)
  IL_0087:  ldloc.0
  IL_0088:  callvirt   instance int64 [System]System.Diagnostics.Stopwatch::get_ElapsedMilliseconds()
  IL_008d:  ret
} // end of method frmResearch::WithOnlyIf
11 голосов
/ 12 октября 2011

Вы можете самостоятельно ответить на этот вопрос с помощью анализатора производительности или просто рассчитать время (поместите функцию в цикл, который вы вызывали много раз).Насколько вам известно, компилятор превращает это в один и тот же код (вы можете проверить)

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

5 голосов
/ 12 октября 2011

Как уже говорилось ранее, производительность вряд ли будет проблемой здесь, если вы заинтересованы в удобочитаемости, хотя вы можете попробовать что-то вроде:

string height = StdHeight;
string width = StdWidth;
if (restrictDimensionsFlag)
{
    height = RestrictedHeight;
    width = RestrictedWidth;
}

и определить ваши стандартные и ограниченные размеры какconsts или readonlys в другом месте (или читайте в config).

3 голосов
/ 13 октября 2011

Предупреждение: Прошло много времени с тех пор, как я работал с определенными оптимизациями ЦП.

Тем не менее, если бы я запрограммировал это на языке ассемблера, в блоке 1 было бы меньше инструкций на цикл, чем в блоке 2. На уровне сборки / машинного кода if / else по существу свободен по сравнению с if, потому что в любом случае расширяется до практически одинаковых инструкций (загрузка, сравнение, условный переход).

Блок1: лучший случай: 5, худший: 6

Load value of myFlag
Compare to const 1
Jump if zero (equal)  :t1
  height = "80%";
  width = "80%";
  Jump :t2
:t1
  height = "60%";
  width = "60%";
:t2

Блок2: лучший случай: 6, худший: 7

height = "80%";
width = "80%";
Load value of myFlag
Compare to const 1
Jump if non-zero (not-equal)  :t1
  height = "60%";
  width = "60%";
:t1

Предостережения:

  • Не все инструкции созданы равными, и переходы, в частности, были более дорогими, когда я изучал сборку ... современные процессоры в основном покончили с этой тенденцией.
  • Современные компиляторы выполняют ОГРОМНУЮ оптимизацию и могут изменить структуру вашего кода с одной из этих конструкций на эквивалентную другую или совершенно другим методом. (Я видел довольно креативное использование индексов массивов, которые также можно использовать в подобных случаях)

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

3 голосов
/ 13 октября 2011

Исправление результата.Я сделал свой собственный тест, и я нашел это значение, которое я считаю более точным.Число итераций: 100 000 000

Флаг = 1

enter image description here

Флаг = 0.

enter image description here

Фактчто худшее время должно быть вдвое лучше, чем неправильное.

Код, который использовался

string height;
string width;
int myFlag = 1;

Console.WriteLine(" ----------- case 1 ---------------");
DateTime Start = DateTime.Now;
for (int Lp = 0; Lp < 100000000; Lp++)
{

    if (myFlag == 1)
    {
        height = "60%";
        width = "60%";
    }
    else
    {
        height = "80%";
        width = "80%";
    }          

}

TimeSpan Elapsed = DateTime.Now - Start;
Console.WriteLine("Time Elapsed: {0} ms",Elapsed.Milliseconds);

Console.WriteLine(" ----------- case 2 ---------------");

DateTime Start2 = DateTime.Now;
for (int Lp = 0; Lp < 100000000; Lp++)
{

    height = "80%";
    width = "80%";

    if (myFlag == 1)
    {
        height = "60%";
        width = "60%";
    }
}

    Elapsed = DateTime.Now - Start2;
    Console.WriteLine("Time Elapsed: {0} ms", Elapsed.Milliseconds);
2 голосов
/ 14 октября 2011

Глядя на IL, я думаю, что у вас есть большая проблема, чем если бы утверждение было быстрее.Поскольку ваши методы не имеют побочных эффектов, компилятор фактически удаляет содержимое операторов if полностью в режиме отладки и полностью удаляет операторы if в режиме выпуска.

Открытие файла .exe в виде, подобном ILSpy проверит это.

Вам придется начать сначала с чего-то, что занимает известное и постоянное количество времени, прежде чем найти ответ на этот вопрос.

2 голосов
/ 13 октября 2011

Более быстрый способ сделать это, вероятно, обрабатывать высоту и ширину как целые / плавающие и приводить их к строкам в последнюю секунду ... при условии, что вы выполняете эту операцию достаточно часто, чтобы удаленно иметь значение (подсказка: вы не).

0 голосов
/ 13 октября 2011

Я обычно использую метод Block # 2 только потому, что знаю, что для рассматриваемых переменных изначально установлены значения по умолчанию

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...