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 답변 덕분에 여기에 있습니다 ) 테스트 한 코드 블록이 if-else 및 if 블록의 할당을 제외하고 변수 높이와 너비를 사용하지 않는 즉시 기 때문에 Code Block-1 및 2 에서 컴파일러는 문제의 if 및 if-else 블록을 완전히 제거하여 IL 코드를 최적화하여 여기에서 테스트에 대한 잘못된 결과를 표시합니다 .
코드 블록을 모두 업데이트하여 높이와 너비의 값을 파일에 기록하여 다시 사용하고 컴파일러가 테스트 블록을 실행하도록 강제했지만 (희망) 실제 파일 작성 부분이 코드에서 관찰 할 수 있습니다. 테스트 결과에 영향을주지 않습니다.
업데이트 된 결과, C # 및 IL 코드입니다.
결과
블록 # 1
myFlag = 1: 1688 Milliseconds
myFlag = 0: 1664 Milliseconds
블록 # 2
myFlag = 1: 1700 Milliseconds
myFlag = 0: 1677 Milliseconds
C # .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;
}
ildasm.exe에 의해 생성 된 IL 코드
블록 # 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)보다 빠르게 실행된다 말할 수 있습니다 .
시험 결과
블록 1 의 10,000,000 회 반복
myFlag = 0: 23.8ns per iteration
myFlag = 1: 23.8ns per iteration
블록 2 의 10,000,000 회 반복
myFlag = 0: 23.8ns per iteration
myFlag = 1: 46.8ns per iteration
블록 2 는 블록 1보다 96 % 느립니다 . 블록 2 는 비관적 인 경우에 두 배의 작업을 수행하기 때문에 의미 가 있습니다.
상황에 따라 어느 쪽이든 선호합니다. 경우
myFlag
없는 거의 지금까지 1, 그것은 우리가 처리 해야하는 에지 경우로서 밖으로 서 싶어요 . 둘 다 똑같이 가능성이있는 권한if-else
구문을 원합니다 . 그러나 그것은 사실이 아니라 선호입니다.
다음 명령으로 넘어 가지 않고 멈춤습니다. 사라진 펜티엄 시대에는 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보다 더 잘 수행되지 않습니다.
여기에서 성능 향상은 내가 마이크로 마이크로 마이크로 최적화라고 부르는 튜닝에 미미합니다. 이 작업을 몇 백만 번 계획하지 않는 한 여기에서 가독성을 높이십시오.
편집 : (re : 게임에있는 질문)
제 생각에는 첫 번째가 더 읽기. 각 경우에 대한 단순화가 무엇인지 준비된 형식으로 명시 적으로 보여줍니다. 두 번째는 케이스를 검토하는 방법을 검토하여 코드를 결정해야합니다. 원근법을 이해하기 위해 원래 선언 / 초기화 와이 특정 코드 블록 사이에 50 줄의 코드를 상상해. 그 경우에 그것이 불분명 해지면 그것은 나를 위해 그것을 것입니다.
업데이트 됨
Matthew Steeples 답변 에 따라 코드를 업데이트하고 Lou Franco 에 따라 Release 빌드에서 코드를 테스트 한 후 If-Else blcoks가 if 블록보다 성능이 더 우수하다는 것을 알았습니다.
내 테스트 응용 프로그램에서 다음 코드 블록을 사용했습니다.
C # .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
ildasm.exe에 의해 생성 된 IL 코드
블록 # 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
성능 분석기를 사용 하여이 질문에 직접 답하거나 타이밍 만 제출할 수 있습니다. (번 호출하는 루프에 함수를 넣음). 아시다시피 컴파일러는 동일한 코드로 변환합니다 (확인할 수 있음).
아마도 괜찮은 마이크로 최적화에 대해 걱정할 필요가 없습니다. 도구에서 최적화 할 수있는 항목을 알려줄 때까지 가장 읽기 쉬운 코드를 작성하십시오.
앞서 말했듯이 성능은 여기서 문제가되지 않습니다. 가독성에 관심이있는 권한이 다음과 같은 것을 시도해 볼 수 있습니다.
string height = StdHeight;
string width = StdWidth;
if (restrictDimensionsFlag)
{
height = RestrictedHeight;
width = RestrictedWidth;
}
표준 및 크기를 다른 곳에서 const 또는 readonlys로 정의합니다.
결과 수정. 나는 내 자신의 테스트를 더 발견했다. 반복 횟수 : 100,000,000
플래그 = 1
플래그 = 0.
최악의 경우라는 사실은 두 배가 있다는 사실은 있습니다.
사용 된 코드
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);
경고 : 특정 CPU 최적화 작업을 한 지 오래되었습니다.
즉, 어셈블리 언어로 이것을 코딩하면 블록 1은 블록 2보다 루프 당 명령어가 더 적을 것입니다. 어셈블리 / 기계 코드 수준에서 if / 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
주의 사항 :
- 모든 명령이 동일하게 생성되는 것은 아니며 특히 어셈블리를 공부할 때 점프 비용이 더 많이 드는 경향이있었습니다. 현대 프로세서는 기본적으로 이러한 경향을 없앴습니다.
- Modern compilers do a HUGE amount of optimization, and may change the structure of your code from either one of these constructs to the equivalent of the other, or a completely different method entirely. (I've seen some rather creative use of array indices that could be used in cases like this as well)
결론 : 일반적으로 기계어 코드 수준에서도이 두 흐름 간의 차이는 매우 적습니다. 자신에게 가장 잘 맞는 것을 선택하고 컴파일러가이를 최적화하는 가장 좋은 방법을 알아 내도록하십시오. 이와 같은 비교적 사소한 경우는 모두 그렇게 처리해야합니다. 예를 들어 계산 수를 변경하거나 값 비싼 함수 호출을 줄이는 매크로 최적화는 적극적으로 구현해야합니다. 이와 같은 사소한 루프 최적화는 특히 컴파일러가 완료된 후에 실제로 실제 차이를 만들지 않을 것입니다.
이 작업을 수행하는 더 빠른 방법은 아마도 높이와 너비를 int / floats로 처리하고 마지막 순간에 문자열로 캐스팅하는 것입니다 ...이 작업을 원격으로 문제가 될만큼 자주 수행한다고 가정합니다 (힌트 : 그렇지 않습니다).
IL을 보면 if 문이 더 빠른 것보다 더 큰 문제가 있다고 생각합니다. 메서드에 부작용이 없기 때문에 컴파일러는 실제로 디버그 모드에서 if 문의 내용을 완전히 제거하고 릴리스 모드에서 if 문을 완전히 제거합니다.
ILSpy 와 같은 파일에서 .exe 파일을 열면 이를 확인할 수 있습니다.
이 질문에 대한 답을 찾기 전에 알려지고 일정한 시간이 걸리는 무언가로 다시 시작해야합니다.
내가 사용하는 것이 블록의 # 2 . 당신이 말했듯이 성능 저하는 무시할 만하지 만 확실히 더 짧고 읽기 쉽습니다. 기본적으로 특정 조건이 충족되지 않는 한 기본값을 변수로 설정합니다.
블록 # 2가 더 읽을 수 있습니다. 그러나 국제적인 코딩 표준이 있습니까? 가능한 한 많이 공연하거나 지속적인 개선을 제안합니다.
블록 # 1의 성능에 따라 높이와 너비는 null 값으로 초기화 할당됩니다 (조건에 관계없이). 성능 차이가 거의 없습니다.
또한 ILDASM으로 IL을 확인 했습니까?
문제의 변수가 처음에 사용되어 설정되어있는 것이 있기 때문에 일반적으로 Block # 2 방법을 사용합니다.
참고 URL : https://stackoverflow.com/questions/7741033/does-if-perform-better-than-if-else
'ProgramingTip' 카테고리의 다른 글
Javascript를 사용하여 정수를 가장 가까운 10으로 반올림하는 방법 (0) | 2020.11.16 |
---|---|
Android의 사용자 지정 대화 상자 : 제목을 중앙에 배치해야 할 필요가 있습니까? (0) | 2020.11.16 |
어떤 것이 더 빠르고 더 낫입니까? (0) | 2020.11.16 |
Parcelable의 하위 클래스를 다른 Parcel에 작성 (0) | 2020.11.16 |
도구를 투명하게 만드는 방법은 무엇입니까? (0) | 2020.11.16 |