65

Which one of these blocks of code performs better, and which one of them is more readable? I'd guess the gain would be negligible, particularly in the second block. I am just 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 i tested the above code were that both the blocks performed the same

Block #1

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

Block #2

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

But one important thing i noticed here(thanks to Matthew Steeples answer here) is that since the block of code that i have tested has not used the variables height and width except for assignment in the if-else and if blocks of Code Block-1 and 2 respectively, the compiler has optimized the IL code by completely removing the if and if-else blocks in question thus showing invalid results for our test here.

I have updated both the code blocks to write the values of both height and width to a file thus using them again and forcing the compiler to run our test blocks(I hope), but you can observe from the code that the actual file writing part does not effect our test results

This is the updated results, C# and 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(); 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; } 

Block #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 Code Generated By 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 we can say that the IF-Else block(Block #1) runs faster than the if block(Block #2) as pointed by many in this forum.

13
  • 4
    Try it..? The first one is a lot more readable Commented Oct 12, 2011 at 13:46
  • 3
    the compiler might optimise the first one to the second one anyway... Commented Oct 12, 2011 at 13:46
  • 9
    The second one ends up assigning height and width twice in one case. Commented Oct 12, 2011 at 13:47
  • 25
    The first person to profile both code samples, posting numbers, would in my opinion get the accepted answer to this non-ambiguous, non-vague, complete, specifically tailored question that genuinely wants an answer, and which can be reasonably answered in its current form. In other words: stop closing useful questions. Commented Oct 12, 2011 at 13:49
  • 5
    alas, if statements are such a bane once you taste if expressions. in F#: let height,width = if myFlag = 1 then "60%","60%" else "80%","80%" Commented Oct 12, 2011 at 19:27

12 Answers 12

93

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 is 96% slower than Block 1. Makes sense, since Block 2 does twice the work in the pessimistic case.

i prefer either case, depending on the situation. If myFlag is rarely ever 1, then it want it to stand out as the edge case that we have to handle. If both are equally likely, i want the if-else syntax. But that's preference, not fact.


Decades ago, the intel 80286 dual pipeline would stall if a conditional jump was taken, rather than falling through to the next instruction. By the time of the Pentium that went away; the CPU pre-fetches both branch paths. But in the back of my mind i still have a twinge of fear whenever i write code that has the most common outcome in the else clause. Every time i have to remind myself that it doesn't matter anymore.


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 makes IF 96% slower
  • GetPercentageString(0.60) makes IF 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); 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; 

Doing twice the amount of work takes roughly twice the amount of time.

Answer: IF does not perform better than IF-ELSE.


enter image description here

Sign up to request clarification or add additional context in comments.

15 Comments

+1 for considering the burden of 1 extra assignment. Though we have advanced cpus, but we dont have them always everywhere. There are processors still running at 20MHz and everything makes sense there.
@abhinav: 20MHz is still 20 MILLION operations per second. Even in that case, this is a pre-optimization, so unless this is a known performance bottleneck, it's not worth the time it takes to think about it.
Don't bother to save battery power on my handheld when you don't have it. It's a free optimization that costs nothing to do. Granted, it would be useful if the compiler optimized the identical code blocks to the better case.
@Thecrocodilehunter The timing difference comes from the quirk in the OP's sample code that no extra string instances are needed. If the code is fiddled to ensure that a string creation is always done, then Block 2 does twice the amount of work as Block 1. And since not all languages perform string equivalence like C#, it's a good general take-away from the exercise.
@MartinSmith: You could do height = MakeCSSPercentage(0.6) or height = String.Format("{0:g}%", 60) or height = width/GetGoldenRatio() The point is to examine the question asked, "Does IF perform better then IF-ELSE?"
|
45

The performance gain here is negligible to the tune I'd call this micro-micro-micro-optimization. Go for readability here unless you plan to do this a couple of million times.

Edit: (re: question in comments)

In my opinion the first one is the more readable. It explicitly shows in a ready format what the strings should be for each case. The second one omits a case, so a reviewer would have to look through other areas of the code to determine the default value. To put it into perspective, imagine 50 lines of code between the original declaration/initialization and this particular code block. If it becomes unclear in that case then that would decide it for me.

5 Comments

@zzzzBov: I figured by the time I hit save there would 50 identical answers anyway :)
@Joel Can you give your opinion on which of them is more readable, b'coz i see mixed answers in the forum
"micro-micro-micro-optimization" Hmmm, "atto-optimization"? :P
Who would put 50 lines of code between the declaration and initialization of the variables? Personally, if the intent is that you have a set of defaults, then a single condition that changes the defaults, I like the second because it communicates that intent better. If the cases are equally likely, i.e., there are two different modes neither of which is a "default", then the first example is better.
@BoltClock Technically it's only milli-micro optimization, since the difference between the two is on the order of tens of nanoseconds (i.e. milli-microsecond)
13

Updated

After updating the code according to Matthew Steeples answer and testing the code in Release build according to Lou Franco, i found that the If-Else blcoks perfrom better than the if block although marginally

I used the following code blocks in my test application

C#.net Code

Block #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; } 

Block #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; } 

The following are the results for Release build

Results for 1000000 Iterations

Block #1

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

Block #2

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

IL Code Generated By 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 

1 Comment

Did you try it with a release build?
11

You can answer this question yourself with a performance analyzer or just timing it (put the function in a loop that you call many times). For all you know, the compiler turns this into the same code (you can check)

Probably you shouldn't worry about these kinds of micro-optimizations. Write the most readable code until your tools tell you what to optimize.

1 Comment

France, I did as you said and posted my answer, hope it helps the community stackoverflow.com/questions/7741033/…
5

As said before performance isn't likely to be an issue here, if you're interested in readability though you might want to try something like:

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

and define your std and restricted sizes as consts or readonlys elsewhere (or read in from config).

Comments

3

Correcting the result. I did my own test and I found this value which I think is more accurate. No of iterations : 100,000,000

Flag = 1

enter image description here

Flag = 0 .

enter image description here

The fact that the worse case time should be twice the best case is wrong.

The code that was used

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

4 Comments

does the compiler figure out that myFlag = 1 at compile-time, and optimize away the check? If so, perhaps you should set myFlag at runtime (using the system clock or PRNG).
I think it does not optimize it. The condition is the same for both cases anyways. The test focuses specifically on if and if-else timing.
@Thecrocodilehunter Can you please confirm these are values from the release build of your test application, please see my update question for more
It was in Active mode. change it to release mode and the result are about the same. Flag-0: 406/421, Flag-1:406/453. The do vary a little bit.
3

Warning: It's been a while since I worked with specific CPU optimizations.

That said, if I were to code this in assembly language, Block 1 would have fewer instructions per loop than block 2. At the assembly/machine code level, if/else is essentially free when compared to if, because either case expands to essentially the same instructions (load, compare, conditional-jump).

Block1: best case: 5, worst: 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: best case: 6, worst: 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 

Caveats:

  • Not all instructions are created equal, and jumps in particular tended to be more expensive when I was studying assembly... modern processors have basically done away with this tendency.
  • 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)

Conclusion: In general, the difference, even at the machine code level will be quite minimal between these two flows. Chose the one that works best for you, and let the compiler figure out the best way to optimize it. All relatively minor cases like this should more or less be treated that way. Macro-optimizations which change the number of computations for example, or reduce expensive function calls should be aggressively implemented. Minor loop optimizations like this are unlikely to make a real difference in practice, especially after the compiler is through with it.

Comments

2

The faster way to do this is probably treat height and width as ints/floats and cast them to strings at the last second ... assuming you're doing this operation frequently enough to remotely matter (hint: you're not).

Comments

2

Looking at the IL I think you've got a bigger problem than which if statement is quicker. Because your methods have no side effects the compiler is actually removing the contents of the if statements entirely in debug mode, and removing the if statements entirely in release mode.

Opening up the .exe file in something like ILSpy will verify this.

You'll have to start again with something that takes a known and constant amount of time before finding out the answer to this question.

Comments

0

I would use Block #2. The performance hit is negligible, as you said, but it's definitely shorter and easier to read. Essentially, you are setting default values to your variables unless a specific condition is met.

2 Comments

This will create garbage, if if statement will became true.
@VMAtm: And what is "garbish"?
0

Block #2 is more readable. However, does your company have coding standards? If so, I would following them as much as possible or suggest consistent improvements.

As per performance in Block #1 height and width are initialized with null values, but then assigned anyway (regardless of condition). Near zero performance difference.

Also, did you check the IL with ILDASM?

Comments

0

I usually use the Block #2 method just because I know the variables in question are initially set to their defaults

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.