Question

I have been unable to find a list of the comparative performance of MSIL instructions. One approach may be 'the more lines, the more work the processor is doing (in principle); however, how wise is this?

Say I want to compare two simple algorithms. One with a private class member:

private Point location;
public bool IsClose(Point locationToCheck, int distance)
{
    int deltaX = Math.Abs(this.location.X - locationToCheck.X);
    return deltaX <= distance;
}

And a static function:

public static bool IsClose(Point x, Point y, int distance)
{
    int deltaX = Math.Abs(x.X - y.Y);
    return deltaX <= distance;
}

Both are compiled as normal (release, no flags, VS2013, .NET 4.5) and the IL is copied from ILSpy.

MSIL (instance variable)

IL_0000: ldarg.0
IL_0001: ldflda valuetype [System.Drawing]System.Drawing.Point ClassLibrary1.Class1::location
IL_0006: call instance int32 [System.Drawing]System.Drawing.Point::get_X()
IL_000b: ldarga.s locationToCheck
IL_000d: call instance int32 [System.Drawing]System.Drawing.Point::get_X()
IL_0012: sub
IL_0013: call int32 [mscorlib]System.Math::Abs(int32)
IL_0018: stloc.0
IL_0019: ldloc.0
IL_001a: ldarg.2
IL_001b: cgt
IL_001d: ldc.i4.0
IL_001e: ceq
IL_0020: ret

MSIL (static, local arguments)

IL_0000: ldarga.s x
IL_0002: call instance int32 [System.Drawing]System.Drawing.Point::get_X()
IL_0007: ldarga.s y
IL_0009: call instance int32 [System.Drawing]System.Drawing.Point::get_X()
IL_000e: sub
IL_000f: call int32 [mscorlib]System.Math::Abs(int32)
IL_0014: stloc.0
IL_0015: ldloc.0
IL_0016: ldarg.2
IL_0017: cgt
IL_0019: ldc.i4.0
IL_001a: ceq
IL_001c: ret

It seems like using the instance variable is making the algorythm first have to load the instance (ldarg.0) then get the property (ldflda val...) then perform the calculation (the rest) wheras the static only needs to load the local (ldarga.s x) and do it.

My novice understanding predisposes me to think that the second would be more performant as it doesn't require the indirection of accessing the instance variable (this.location) and instead just picks up all components from the .locals.

In that case, assuming that I actually prefer the static approach, would it be the best approach? Is there a bias when designing these kinds of systems toward instance methods because they are convenient (e.g. someEnemy.IsClose(thePlayer, 20); sounds linguistically nicer).

Was it helpful?

Solution

It doesn't make much sense to compare the efficiency of IL instructions, because IL is not what's actually executed, the native machine code (x86, x64, ARM, …) is. The JIT compiler performs various optimizations, so guessing performance from IL would be very inaccurate.

Looking at the compiled machine code is better, but it still won't be very accurate, especially because of caches (their effect on performance is very hard to guess).

So, when trying to find out which version of some code is faster, the most important thing you should do is to actually measure it.

When you have your measurements and you're trying to understand them, that's when looking at IL or, even better, machine code, becomes useful.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top