I am developing a 2D tile-based RPG game for desktop and (hopefully) Android. To represent a tile location in the game, I am using a class called Location, which has a value for x, y, and room. room refers to the Room that the Location is in. I use the Location class for calculations like whether a tile is passable or impassable, the tile that a character is facing, etc. Originally, I used x, y, and room values for the character, game objects, etc. classes, but decided to replace them with instances of Location instead.From here, here, and elsewhere, I am under the impression that instantiating these Location objects over and over would be less than ideal for performance, especially on Android platforms. But it also seems like pooling (see the links) Locations is too much work to implement. For example, I can get a new Location from a Location and a Direction (an enum) by calling Location.add(Direction) which I would use in character movement calculations (depending on what Direction the player is directing). It would be extremely inconvenient to have to manually call free on an object that I intend to use only in one line, for example in pseudocode character.setLocation(character.getLocation().add(character.facingDirection)) versusvar tempLocation = character.getLocation().add(character.facingDirection) // assuming for convenience that the add method uses a global pool of Location scharacter.setLocation(tempLocation)tempLocation.free() // assuming this frees it from the global poolThe idea of using a Location class instead of x, y, and room values in every relevant object is to simplify the process of coding, not make it more complex. (And, of course, it seems to me the correct object-oriented way). Are there any other viable ways to maintain decent performance without avoiding the Location class altogether? Or, for that matter, is performance even a concern in this case?For completion's sake, I'm using Java, Scala, and LibGDX.
How to avoid repeated instantiation and garbage collection for a trivial class?
object oriented;object oriented design;performance;optimization;game development
Instantiating and collecting small, short-lived, temporary objects, is perfectly fine. It is what modern garbage collectors are good at.Modern (generational) garbage collectors are built on a couple of assumptions: most objects die young, most objects are small, most objects don't escape, most objects are immutable, older objects don't contain references to younger objects. Only objects which violate these assumptions are expensive, and your objects fulfill these assumptions. Allocating an object in the young generation is just bumping a pointer (just like stack allocation in C, and cheaper than malloc) and collecting the young generation is O(#survivors), so if most objects are dead, collection is cheap also.Re-using and pooling objects OTOH violates them: it artificially lengthens the lifetime of objects, the pool itself is large, references become non-local, objects are needlessly mutable (and needlessly mutated). Unless you have specific evidence to the contrary, object re-use and pooling is going to hurt GC, not help it.You may note that the assumptions are trivially true for functional programming. Indeed, even though most modern garbage collectors are developed for imperative OO platforms (e.g. Sun's G1 for HotSpot, IBM's Metronome for J9, the .NET GC, Mono's scgen, Immix, Azul's Pauseless Collector, etc.), they end up being pretty good at FP. For example, Azul has demonstrated running the famous Clojure Ant Simulation Example on an 864 core machine with 768 GiByte of RAM with 700 parallel threads generating 20 GiByte/s of garbage, and the GC never induced noticeable pauses and never needed more than 20-30 cores (or in other words never more than ~30% of the available CPUs).