Created
November 13, 2016 00:01
-
-
Save gregoryyoung/5f465f3145bc56793a0e8da9a1ee7b01 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The performance implications of try are more severe than I had thought. I thought it was just code within the try block that isn’t optimized. It turns out it’s everything around the block too. Take this code: | |
object syncObject = new Object(); | |
[System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)] | |
public int Member ( ) | |
{ | |
int value = 10; | |
Monitor.Enter(this.syncObject); | |
try | |
{ | |
} | |
finally | |
{ | |
Trace.WriteLine("ding"); | |
} | |
Monitor.Exit(this.syncObject); | |
return value; | |
} | |
Compiled with TRACE defined we get this: | |
!u 011d01e0 | |
Normal JIT generated code | |
WindowsApplication2.Tester.Member() | |
Begin 011d01e0, size 65 | |
>>> 011D01E0 55 push ebp | |
011D01E1 8BEC mov ebp,esp | |
011D01E3 57 push edi | |
011D01E4 56 push esi | |
011D01E5 53 push ebx | |
011D01E6 83EC1C sub esp,1Ch | |
011D01E9 33C0 xor eax,eax | |
011D01EB 8945E8 mov dword ptr [ebp-18h],eax | |
011D01EE 894DD8 mov dword ptr [ebp-28h],ecx | |
011D01F1 C745DC0A000000 mov dword ptr [ebp-24h],0Ah | |
011D01F8 8B45D8 mov eax,dword ptr [ebp-28h] | |
011D01FB 8B480C mov ecx,dword ptr [eax+0Ch] | |
011D01FE E8D63ACA78 call 79E73CD9 (System.Threading.Monitor.Enter(System.Object), mdToken: 060011b7) | |
011D0203 C745E400000000 mov dword ptr [ebp-1Ch],0 | |
011D020A C745E8FC000000 mov dword ptr [ebp-18h],0FCh | |
011D0211 683C021D01 push 11D023Ch | |
011D0216 EB00 jmp 011D0218 | |
011D0218 8B0DC46B3802 mov ecx,dword ptr ds:[02386BC4h] | |
011D021E E8FDF53279 call 7A4FF820 (System.Diagnostics.Trace.WriteLine(System.String), mdToken: 06000e9a) | |
011D0223 58 pop eax | |
011D0224 FFE0 jmp eax | |
011D0226 8B45D8 mov eax,dword ptr [ebp-28h] | |
011D0229 8B480C mov ecx,dword ptr [eax+0Ch] | |
011D022C E8223DCA78 call 79E73F53 (System.Threading.Monitor.Exit(System.Object), mdToken: 060011b9) | |
011D0231 8B45DC mov eax,dword ptr [ebp-24h] | |
011D0234 8D65F4 lea esp,[ebp-0Ch] | |
011D0237 5B pop ebx | |
011D0238 5E pop esi | |
011D0239 5F pop edi | |
011D023A 5D pop ebp | |
011D023B C3 ret | |
011D023C C745E800000000 mov dword ptr [ebp-18h],0 | |
011D0243 EBE1 jmp 011D0226 | |
Notice 0Ah assigned at 011D01F1 before the try block , it’s not optimizing the assignment of 10 to value away. Whereas if we undefined TRACE the same code produces: | |
!u 011d01e0 | |
Normal JIT generated code | |
WindowsApplication2.Tester.Member() | |
Begin 011d01e0, size 1a | |
>>> 011D01E0 56 push esi | |
011D01E1 8BF1 mov esi,ecx | |
011D01E3 8B4E0C mov ecx,dword ptr [esi+0Ch] | |
011D01E6 E8EE3ACA78 call 79E73CD9 (System.Threading.Monitor.Enter(System.Object), mdToken: 060011b7) | |
011D01EB 8B4E0C mov ecx,dword ptr [esi+0Ch] | |
011D01EE E8603DCA78 call 79E73F53 (System.Threading.Monitor.Exit(System.Object), mdToken: 060011b9) | |
011D01F3 B80A000000 mov eax,0Ah | |
011D01F8 5E pop esi | |
011D01F9 C3 ret | |
That’s a HUGE difference, notice the optimization of 10 to a simple return AFTER the try block. Not to mention, if Monitor.Exit is an implicit volatile write where is my guarantee that “the write is guaranteed to happen after any memory references prior to the write instruction in the CIL instruction sequence.” | |
__ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment