After some code inspection we nailed it down to a foreach loop, something as simple as:
var list = new List<int>();
// the code bellow allocates memory. 
foreach(var item in list)
{
}
Interestingly enough, when compiled against C# 3.5 / 4.0 compilers we could not reproduce this behavior; it was only when compiling on Mono 2.6 (on mono 2.10 it didn't happened).After some investigation (and head banging) we found the issue; for reasons that I'll not explain here (basically to avoid gc allocations) the enumerator returned by List
finally
{
     IL_0048: ldloc.2
     IL_0049: box valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator< int32>
     IL_004e: callvirt instance void [mscorlib]System.IDisposable::Dispose()
     IL_0053: endfinally
}
Well, it happens that MS C# compiler (and newer mono ones also) emit different IL for that finally block:finally
{
     IL_004b: ldloca.s 3
     IL_004d: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator< int32>
     IL_0053: callvirt instance void [mscorlib]System.IDisposable::Dispose()
     IL_0058: nop
     IL_0059: endfinally
}
See, no box instruction. Instead of boxing, the compiler loads the value type address and then asks the runtime to handle that address as a reference to IDisposable.Really interesting (at least IMHO)
Happy codding!
 
 
No comments:
Post a Comment