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).