Sprite class and memory effeciency
#1 Members - Reputation: 100
Posted 29 August 2011 - 03:06 PM
However, I've come to an unfortunate realization about the design of my sprite class: given that the intended project is a retro turn-based strategy game, I know in advance that the non-basic fields of the sprite class will be unused by 95% of the sprites or more (at any given time). Almost none of them will be scaled or rotated or colorized or have motion blur or even animated outside of brief periods when actions are performed. Otherwise, they are largely static. So, in the most straightforward implementation, every Sprite would have fields for scaling, rotation, colorization, and multiple other properties, when I KNOW that this will be wasted memory at least 95% of the time. What can I do about this? Any recommendations?
#2 Moderators - Reputation: 8419
Posted 30 August 2011 - 12:01 AM
[Work - ArenaNet] [Epoch Language] [Scribblings] [Journal - peek into my shattered mind]
#3 Members - Reputation: 172
Posted 30 August 2011 - 12:38 AM
But you can make the sprites extendable with whatever you need.
Edit:
Further more, pre-optimizations are the devil. Fix it when it becomes a problem.
I have no idea where you get the number 95% from.
A sprite class in general takes up a couple of bytes, the big memory hogs are the textures.
#4 Members - Reputation: 1121
Posted 30 August 2011 - 02:06 AM
Important rule of software engineering; "When in doubt, use brute force". It was coined by Ken Thompson to describe his philosophy for developing UNIX. That's why so much of UNIX is lookup tables or singly linked lists. Really simple structures that turned not to need optimising. They'd probably never have finished UNIX if they'd worried about optimising all of them up front.
#5 Members - Reputation: 100
Posted 30 August 2011 - 10:41 PM
What language are you using?
Java.
Thanks for the replies and I do appreciate the sentiment. I admit that I have a some recurring issues with potentially-unimportant optimizations, but I am particularly bothered in this case by the fact that the significant majority of the class's members would be unused in the general case. It's not a matter of fussing about trimming 10% off the top of something, but rather that 90+% percent of it would be 'waste'. A rough calculation suggests something between 100-200 bytes of overhead for rarely-used properties (depending on exactly how many of them I implement), and only about 16 bytes for the ones that everything needs all the time. Such an imbalance really strikes me as wasteful and sloppy, but several schemes I've considered for reducing the memory footprint (like encapsulating related groups of properties in other classes, and letting the Sprite maintain null references if it doesn't use that type of property) significantly complicate the logic and don't always save that much memory either, due to needing to store object references and per-object overhead.
As for the target hardware, I'm aiming for at least 5 year old computers (and really, actually aiming older than that, but haven't been able to even find one older than that in person, to benchmark stuff against) And yes, I realize that there's probably no realistic way to end up with a memory footprint too large even for that, but I don't feel it's good practice to accept too much 'padding', if one can avoid it.
I was just wondering if there were some conventional strategies for this sort of thing, or whether it really was a typical compromise to just throw every conceivable type of property or effect that requires specific tracking into the sprite class, and accept the wastage.
Code doesn't have to be perfect or brilliant. It only has to be "good enough".
This is probably more true than I'm comfortable internalizing, I admit...
#6 Moderators - Reputation: 8419
Posted 31 August 2011 - 12:26 AM
[Work - ArenaNet] [Epoch Language] [Scribblings] [Journal - peek into my shattered mind]
#7 Crossbones+ - Reputation: 5344
Posted 31 August 2011 - 01:33 AM
L. Spiro
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums
#12 Members - Reputation: 2369
Posted 31 August 2011 - 10:19 AM
You're using Java. The most memory inefficient platform there is.Such an imbalance really strikes me as wasteful and sloppy
Instead of worrying about fixed per-object member overhead, minimize allocations to some reasonable extent. The bulk amount of memory doesn't really matter all that much, considering JVM requires about 4x the working set to run without GC hogging up all the resources. Or, if you have 250MB textures (somewhat permanent), expect JVM to require 1GB of RAM. If your entire overhead of this state is then 100MB, it's simply absorbed in the reserve.
#13 Members - Reputation: 100
Posted 31 August 2011 - 02:41 PM
Can you factor the most-commonly used members into a base class or three, and then use subclasses for the special cases that need more data?
I considered this. The main issue in this case is that while I know that most sprites will not need any extended properties at any given time, I don't easily know in advance which of them will need them. For example, consider a motion trail effect that can be applied to any moving sprite. This is only used for certain special attack and spell animations, but these could theoretically apply to any creature or projectile. It's just that, in practice, 99% of creature and projectile sprites will never use it. The same thing applies to a great many of the extended properties.
Given that I can't make very good advance judgments about when to give a creature a (for example) BasicSprite over an ExtendedSprite, this would seem to require a way to construct an ExtendedSprite from a BasicSprite (and vice versa), and convert a creature's sprite from one to the other whenever advanced effects are applied to it or when those advanced effects end. This... seems unpleasantly cumbersome, to say the least.
You're using Java. The most memory inefficient platform there is.
The fact that a platform itself is inefficient doesn't mean that one should disregard efficiency entirely. If anything, it might be even more important since there are many ways to incur overhead.
Instead of worrying about fixed per-object member overhead, minimize allocations to some reasonable extent. The bulk amount of memory doesn't really matter all that much, considering JVM requires about 4x the working set to run without GC hogging up all the resources. Or, if you have 250MB textures (somewhat permanent), expect JVM to require 1GB of RAM. If your entire overhead of this state is then 100MB, it's simply absorbed in the reserve.
While you make an interesting point about 'free' memory within the allocated heap size, texture memory actually resides outside the JVM entirely (and isn't garbage-collected, etc.) So even if I did have 250MB of textures (In practice, I would have much, much less), this wouldn't buy any 'free' heap space to use for other purposes. (Although, more fortunately, this also means it doesn't force memory usage much larger than the textures themselves, either)
#14 Moderators - Reputation: 8419
Posted 31 August 2011 - 05:01 PM
[Work - ArenaNet] [Epoch Language] [Scribblings] [Journal - peek into my shattered mind]
#15 Members - Reputation: 100
Posted 02 September 2011 - 12:46 PM
At some point you have to decide which tradeoff to make: accept simpler code with higher memory consumption, or accept more complex code to get the lower memory usage. Depends on your priorities.
Reasonable enough, really. So much of development is about making tradeoffs, anyway: performance vs. flexibility, and so forth. In the end, saving a couple hundred KB probably isn't worth the additional code complexity of encapsulating property groups, checking a half-dozen things for null references each frame, and creating/destroying property classes as effects become active or inactive. Even when this extra memory is almost entirely a result of overhead known to be unnecessary ahead of time in the general case. It may simply be the cost of avoiding something potentially worse.
I had hoped there might be some obvious alternate way to go about this, but if not... Nearly all the source code I've perused to examine their rendering systems either had sprites that were much less flexible and capable in the first place, or legitimately needed most of their extended properties for the majority of their sprites. But it's probably better to err on the side of flexibility and clarity than worry about memory that is probably largely an ideological concern at this point.






