Back in 2007, I took some SharePoint training from Todd Bleaker (MVP, owner of MindSharp, and SharePoint guru). At one point he posed a question about the performance of the following methods:
public string OptionOne()
{
string str = "Hello World";
return str;
}
public string OptionTwo()
{
string str;
str = "Hello World";
return str;
}
public string OptionThree()
{
string str = null;
str = "Hello World";
return str;
}
public string OptionFour()
{
return "Hello World";
}
I took the challenge and wrote the above methods. Then to evaluate the probable performance I compiled the code and opened the resulting assembly in Reflector. Here is the Reflector output:
public string OptionOne()
{
return "Hello World";
}
public string OptionTwo()
{
return "Hello World";
}
public string OptionThree()
{
return "Hello World";
}
public string OptionFour()
{
return "Hello World";
}
You may notice that all the methods appear the same. What happened? Compiler optimization? To find out I checked the IL, shown below:
.method public hidebysig instance string OptionOne() cil managed
{
.maxstack 1
.locals init (
[0] string str,
[1] string CS$1$0000)
L_0000: nop
L_0001: ldstr "Hello World"
L_0006: stloc.0
L_0007: ldloc.0
L_0008: stloc.1
L_0009: br.s L_000b
L_000b: ldloc.1
L_000c: ret
}
.method public hidebysig instance string OptionTwo() cil managed
{
.maxstack 1
.locals init (
[0] string str,
[1] string CS$1$0000)
L_0000: nop
L_0001: ldstr "Hello World"
L_0006: stloc.0
L_0007: ldloc.0
L_0008: stloc.1
L_0009: br.s L_000b
L_000b: ldloc.1
L_000c: ret
}
.method public hidebysig instance string OptionThree() cil managed
{
.maxstack 1
.locals init (
[0] string str,
[1] string CS$1$0000)
L_0000: nop
L_0001: ldnull
L_0002: stloc.0
L_0003: ldstr "Hello World"
L_0008: stloc.0
L_0009: ldloc.0
L_000a: stloc.1
L_000b: br.s L_000d
L_000d: ldloc.1
L_000e: ret
}
.method public hidebysig instance string OptionFour() cil managed
{
.maxstack 1
.locals init (
[0] string CS$1$0000)
L_0000: nop
L_0001: ldstr "Hello World"
L_0006: stloc.0
L_0007: br.s L_0009
L_0009: ldloc.0
L_000a: ret
}
What is really happening is that Reflector is making a best guess optimization as to what the original code looked like. We can clearly see in the IL that OptionFour is probably the most performant, and OptionThree is probably the least. This is because OptionThree is loading a null and storing it in local 1, then loading the string and storing it in the same location, making the first load unnecessary.
Reflector can be a great tool to use for analyzing possible performance, as well as debugging assemblies. If you don’t have it, download it today: www.red-gate.com/products/reflector/