IF работает лучше, чем IF-ELSE?

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

Блок # 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

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

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

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

Результаты

Блок # 1

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

Блок # 2

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

С#.net Код

Блок # 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 (Block # 2), как указано многими в этом форуме.

Ответ 1

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

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; CPU предварительно использует оба пути ветвления. Но в глубине души я все еще испытываю приступ страха всякий раз, когда пишу код, который имеет наиболее общий результат в предложении 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 не работает лучше IF-ELSE.


enter image description here

Ответ 2

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

Изменить: (повторно: вопрос в комментариях)

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

Ответ 3

Обновление

После обновления кода в соответствии с Matthew Steeples ответьте и протестируйте код в сборке Release в соответствии с Lou Franco, я обнаружил, что If-Else blcoks perfrom лучше, чем if, хотя и незначительно

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

С#.net Код

Блок # 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

Ответ 4

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

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

Ответ 5

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

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

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

Ответ 6

Исправление результата. Я сделал свой собственный тест, и я нашел это значение, которое, я думаю, более точно. Нет итераций: 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);

Ответ 7

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

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

Block1: лучший случай: 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

Block2: лучший случай: 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

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

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

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

Ответ 8

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

Ответ 9

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

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

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

Ответ 10

Я бы использовал Блок # 2. Как вы сказали, хит производительности пренебрежимо мал, но он определенно короче и легче читается. По существу, вы устанавливаете значения по умолчанию для своих переменных, если не выполняется определенное условие.

Ответ 11

Блок №2 более читабельен. Однако есть ли в вашей компании стандарты кодирования? Если это так, я бы следил за ними как можно больше или предлагал последовательные улучшения.

В соответствии с производительностью в блоке №1 высота и ширина инициализируются нулевыми значениями, но затем назначаются в любом случае (независимо от состояния). Почти нулевая разница в производительности.

Кроме того, вы проверили IL с ILDASM?

Ответ 12

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