ILDasm Helpful Hack
I do not want to learn "yet another programming language", especially a low-level one like Microsoft's Intermediate Language (IL). And yet, sometimes it's useful to look under the hood and see what in tarnation is going on. And that means knowing something about IL.
I was answering a question on optimization (the root cause of a lot of unmaintainable code) and found it useful to generate the IL to show which of two algorithms was quicker. With modern operating systems having dozens of background threads running, simple timing can lead to misleading results. Is the algorithm slow, or was System Restore creating a restore point when we measured?
In order to examine code in IL, it's helpful to delimit sections. But we can't use comments, they are stripped out. So, here is a cheesy way to delimit sections of code. Note the variables assigned to MyInt:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string MyString = string.Empty;
int MyInt;
MyInt = 0xAAAAAAA; // ---- Marker: algorithm A
if (MyString == String.Empty)
MyInt = 1;
else
MyInt = 2;
MyInt = 0xBBBBBBB; // ---- Marker: algorithm B
MyInt = MyString == String.Empty ? 1 : 2;
MyInt = 0xCCCCCCC; // ---- Marker: end test.
}
}
When you create the IL with ILDasm, you can easily see where the markers are. In this case I bolded and underlined them:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 68 (0x44)
.maxstack 2
.locals init ([0] string MyString,
[1] int32 MyInt,
[2] bool CS$4$0000)
IL_0000: nop
IL_0001: ldsfld string [mscorlib]System.String::Empty
IL_0006: stloc.0
IL_0007: ldc.i4 0xaaaaaaa
IL_000c: stloc.1
IL_000d: ldloc.0
IL_000e: ldsfld string [mscorlib]System.String::Empty
IL_0013: call bool [mscorlib]System.String::op_Equality(string,string)
IL_0018: ldc.i4.0
IL_0019: ceq
IL_001b: stloc.2
IL_001c: ldloc.2
IL_001d: brtrue.s IL_0023
IL_001f: ldc.i4.1
IL_0020: stloc.1
IL_0021: br.s IL_0025
IL_0023: ldc.i4.2
IL_0024: stloc.1
IL_0025: ldc.i4 0xbbbbbbb
IL_002a: stloc.1
IL_002b: ldloc.0
IL_002c: ldsfld string [mscorlib]System.String::Empty
IL_0031: call bool [mscorlib]System.String::op_Equality(string, string)
IL_0036: brtrue.s IL_003b
IL_0038: ldc.i4.2
IL_0039: br.s IL_003c
IL_003b: ldc.i4.1
IL_003c: stloc.1
IL_003d: ldc.i4 0xccccccc
IL_0042: stloc.1
IL_0043: ret
} // end of method Program::Main
A quick look at the IL code should tell you which algorithm is fastest…and you don't even have to be a rocket surgeon.
But, of course, as any seasoned developer will tell you: "It's the maintenance stupid!"
I hope you find this helpful.
Steve Wellens
[Update]
My friend Svante pointed out to me that it is the JIT that does the final optimization and you can’t really go by IL to determine which algorithms are quicker. He is correct.
To look at the JIT output…
Go to Tools->Options->Debugging->General and unclick "Suppress JIT optimization on module load." You want the optimization.
Add a breakpoint to the code. Run the program, when the breakpoint hits, right-click the source code and select "Go to Disassembly." I removed the "markers" because they are no longer needed.
JIT Output (edited):
if (MyString == String.Empty)
00000050 mov edx,dword ptr ds:[02CC102Ch]
00000056 mov ecx,dword ptr [ebp-40h]
00000059 call 6A625FB8
0000005e mov dword ptr [ebp-4Ch],eax
00000061 cmp dword ptr [ebp-4Ch],0
00000065 sete al
00000068 movzx eax,al
0000006b mov dword ptr [ebp-48h],eax
0000006e cmp dword ptr [ebp-48h],0
00000072 jne 0000007E
MyInt = 1;
00000074 mov dword ptr [ebp-44h],1
0000007b nop
0000007c jmp 00000085
else
MyInt = 2;
0000007e mov dword ptr [ebp-44h],2
MyInt = MyString == String.Empty ? 1 : 2;
0000008c mov edx,dword ptr ds:[02CC102Ch]
00000092 mov ecx,dword ptr [ebp-40h]
00000095 call 6A625FB8
0000009a mov dword ptr [ebp-50h],eax
0000009d cmp dword ptr [ebp-50h],0
000000a1 jne 000000AD
000000a3 nop
000000a4 mov dword ptr [ebp-54h],2
000000ab jmp 000000B4
000000ad mov dword ptr [ebp-54h],1
000000b4 mov eax,dword ptr [ebp-54h]
000000b7 mov dword ptr [ebp-44h],eax
I hope this extra information is helpful to someone.