I have the following code:
public class Character
{
public Vector2 WorldPixelPosition
{
get { return Movement.Position; }
}
public Vector2 WorldPosition
{
get { return new Vector2(Movement.Position.X / Tile.Width, Movement.Position.Y / Tile.Height); }
}
public Vector2 LevelPosition
{
get { return new Vector2(WorldPosition.X % Level.Width, WorldPosition.Y % Level.Height); }
}
}
Now somewhere else in my code, I make about 2500 calls in a loop to Character.LevelPosition.
This means that per update-cycle, 5000 ‘new’ Vector2s are being made, and on my laptop, it really drops the framerate.
I have temporarily fixed it by creating
var levelPosition = Character.LevelPosition;
before I initiate the loop, but I kinda feel its ugly code to do this everytime I come across a similar situation. Maybe it -is- the way to go, but I want to make sure.
Is there a better or commonly accepted way to do this?
I’m using the XNA-Framework, which uses Vector2‘s.
From what I understand, you should avoid allocating lots of objects from the heap in XNA, because that causes bad performance. But since
Vector2is astruct, we’re not allocating anything on the heap here, so that shouldn’t be the problem here.Now, if you have tight loop, like you do, in a performance-critical application, like a game, you will always have to think about performance, there is no going around that.
If we look at the code for
LevelPosition, you call the getter forWorldPositiontwice and probably some more getters. The getter forWorldPositionprobably calls few other getters. (It’s hard to say what exactly is going on without having the source, because getter call and field access look exactly the same.)Call to a getter, which is actually just a call to a special method, is usually pretty fast and can be even faster if the compiler decides to use inlining. But all the calls add up together, especially if you call them in a loop.
The solution for this is some sort of caching. One option would be to make
LevelPositiona field and devise a system to update it when necessary. This could work, but it could also actually hurt performance if you need to update it more often than you read it.Another solution is, as you discovered, to cache the result in a local variable. If you know that this is correct, i.e. that the value of the property won’t change during the execution of the loop, then that’s awesome! You solved your performance problem and you did it with only a single line of code that’s easily understandable to any programmer. What more do you want?
Let me restate that. You found a solution to your performance problem that:
I think such solution wold be very hard to beat.