I'm working in an old-school 2D game engine (much inspired by Action Arcade Adventure Set) using Allegro.pas (Spam? What Spam? ). I have some stuff done, but now that I've finished with Sprites and before to start with the tile-map stuff I start to concern with memory management.
You know, FPC has two ways to define objects: CLASS and OBJECT. Main difference between CLASS and OBJECT is that CLASS is always referenced and must be created explicitly as it is always dynamic while you can created OBJECT “statically” as you do with RECORD. So let's get the Sprite example. Using CLASS you create a list of sprites this way:
Code:
VAR
Sprites: ARRAY OF TSprite;
BEGIN
SetLength (Sprites, NumSprites);
FOR Ndx := LOW (Sprites) TO HIGH (Sprite) DO
Sprites[Ndx] := Tsprite.Create;
END;
So you have a list of pointers to the actual objects. Then you may end with the sprite list fragmented in the memory (and the more you add and remove sprites, the more fragmented would be).
Using OBJECT:
Code:
VAR
Sprites: ARRAY OF TSprite;
BEGIN
SetLength (Sprites, NumSprites);
FOR Ndx := LOW (Sprites) TO HIGH (Sprite) DO
Sprites[Ndx].Init;
END;
Despite you need to call method Init (mandatory in some cases), you have an actual list of sprites in a continuous memory block.
I’m not an expert in current microprocessor architectures inner (I’ve stuck in the Z-80) but I know a little about caches, and I suspect that the CLASS approach would be a bottleneck when executing next code:
Code:
{ Update and render sprites }
FOR Ndx := LOW (Sprites) TO HIGH (Sprite) DO
BEGIN
Sprites[Ndx].Update (DeltaTime);
Sprites[Ndx].PutSprite
END;
An array of OBJECTs may be faster as the whole ARRAY may be uploaded to the microprocessor cache at once, or in runs of n sprites. The array of CLASS references would be much slower if objects are far from the ARRAY forcing to upload cache in each loop iteration.
Wy the way, using an array of OBJECTs prevents you to use virtual methods, as all OBJECT on the array will be the same type. This can be fixed by using pointers to procedures or event properties instead; as far as I know there’s a microprocessor cache for data and another one for code, so performance won’t be affected so much. This is a bit ugly and can be implemented by simple RECORDs too, but CLASS actually uses that approach internally (the virtual table is just an array of pointers to method) just with compiler magic.
Another bad thing is that inserting and removing sprites will be ugly. Also if you do it dynamically it would take much time to resize the ARRAY. Actually I'm using a linked list implementation right now, but Build engine uses a fixed sized array for data, including sectors and sprites, then uses several internal linked lists to organize them (for example, one linked list for each map sector that links all sprites that are inside sector); most games that use Build add and remove sprites (bullet holes, explossions, smoke…) and Duke Nukem 3D worked quite well in my old 486.
Am I right in my thoughts? Are OBJECT worth of? Does Delphi support OBJECTs too? How much microprocessor caches affect performance? Does a fixed size array of OBJECT counts as pool?
Bookmarks