c# - Does IF perform better than IF-ELSE? -
which 1 of these blocks of code performs better, , 1 of them more readable? i'd guess gain negligible, particularly in second block. curious.
block #1
string height; string width; if (myflag == 1) { height = "60%"; width = "60%"; } else { height = "80%"; width = "80%"; }
block #2
string height = "80%"; string width = "80%"; if (myflag == 1) { height = "60%"; width = "60%"; }
updated
the results when tested above code both blocks performed same
block #1
myflag = 1: 3 milliseconds myflag = 0: 3 milliseconds
block #2
myflag = 1: 3 milliseconds myflag = 0: 3 milliseconds
but 1 important thing noticed here(thanks matthew steeples answer here) since block of code have tested has not used variables height , width except assignment in if-else , if blocks of code block-1 , 2 respectively, the compiler has optimized il code removing if , if-else blocks in question showing invalid results our test here.
i have updated both code blocks write values of both height , width file using them again , forcing compiler run our test blocks(i hope), can observe code actual file writing part not effect our test results
this updated results, c# , il code
results
block #1
myflag = 1: 1688 milliseconds myflag = 0: 1664 milliseconds
block #2
myflag = 1: 1700 milliseconds myflag = 0: 1677 milliseconds
c#.net code
block #1
public long withifandelse(int myflag) { stopwatch mytimer = new stopwatch(); string somestring = ""; mytimer.start(); (int = 0; < 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; }
block #2
public long withonlyif(int myflag) { stopwatch mytimer = new stopwatch(); string somestring = ""; mytimer.start(); (int = 0; < 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 code generated ildasm.exe
block #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
block #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
so can if-else block(block #1) runs faster if block(block #2) pointed many in forum.
test results
10,000,000 iterations of block 1
myflag = 0: 23.8ns per iteration myflag = 1: 23.8ns per iteration
10,000,000 iterations of block 2
myflag = 0: 23.8ns per iteration myflag = 1: 46.8ns per iteration
block 2 96% slower block 1. makes sense, since block 2 twice work in pessimistic case.
i prefer either case, depending on situation. if
myflag
rarely ever 1, want stand out edge case have handle. if both equally likely, wantif-else
syntax. that's preference, not fact.
decades ago, intel 80286 dual pipeline stall if conditional jump taken, rather falling through next instruction. time of pentium went away; cpu pre-fetches both branch paths. in of mind still have twinge of fear whenever write code has common outcome in else
clause. every time have remind myself doesn't matter anymore.
int32 reps = 10000000; private void block1(int myflag) { string width; string height; stopwatch sw = new stopwatch(); sw.start(); (int = 0; < 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(); (int = 0; < 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
makesif
96% slowergetpercentagestring(0.60)
makesif
96% slower
const reps = 10000000; procedure block1(myflag: integer); var width, height: string; i: integer; t1, t2: int64; time: extended; freq: int64; begin queryperformancecounter(t1); := 1 reps begin if myflag = 1 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); := 1 reps begin width := '80%'; height := '80%'; if myflag = 1 begin width := '60%'; height := '60%'; end; end; queryperformancecounter(t2); queryperformancefrequency(freq); time := (t2-t1) / freq * 1000000000 / reps; showmessage(floattostr(time)+ 'ns'); end;
doing twice amount of work takes twice amount of time.
answer: if not perform better if-else.
Comments
Post a Comment