I got the idea for my Space game (it’s a side scrolling spaceship game, like Galaga turned sideways) to reuse the “enemy” objects instead of removing them from use when I don’t need them. So currently I have it set up so that I have an ArrayList that holds all the enemy aliens for that level (starts at 30 and increases as the levels go on). When an alien is hit by the users laser, the Alien is removed from the ArrayList so that it is not iterated over when updating and drawing. Then at the end of the level I add Aliens to the ArrayList until it’s reached the number needed for the next level. My question is, would it be better to just reuse the Alien objects already in the ArrayList instead of removing them when they get hit? My problem is that reusing would require an isAlive() (or some kind of) check on each Alien for every draw and update. Also just a minor question, does anyone know of some good information on how the innards of Java work, like the JVM and the Garbage Collector.
[b]I am a little confused. Are you adding your alien to a secondary list to check if there has been enough aliens on current level?
Why not just use a simple int counter to keep track of how many aliens have spawned or been killed or whatever?[/b]
Although I do not have a super good understanding of the JVM and GC. I don’t think you need to worry about it anymore, the way you are currently doing it.
If you were really concerned, you could just “null” out your variables before you remove it from the list. Because after its out of the Arraylist, you don’t really have anyway to access that data/object anymore. So I think the GC cleans it up because of that.
Anyways, for the small quantity of enemies(a few hundred at most), its probably not a big deal either way. If it was for particles or something high quantity over long periods of time, then maybe an alternative to lots of “new” object calls?
There is one ArrayList, when an Alien is hit by the user’s weapon the Alien is removed from the ArrayList. The ArrayList isn’t just to have the number of Aliens, it holds Alien objects that have a draw method, the Aliens position, and a move method. But for a smaller number of Objects it wouldn’t matter anyway?
The JVM and GC info isn’t really for this specifically, I simply don’t know a lot about them and would like to know more
It’s called object caching pooling and I don’t think you need to do this (premature optimization) because I doubt that creating your alien objects is very costly, or that you do it so often that it poses a problem. But if you want to know how to do it properly, just search ‘object pooling.’
Don’t do object pooling - unless you’ve got something that takes a long time to construct. Also don’t do it if it takes a lot of clean up work.
Consider it in cases where you might be generating thousands of them every second.
I second that. Keep thing simple until you go speed problem. When you have problem, do some profiling, the problem may not even be object creation.
Well if it is for Android, object creation do cost a lot.
But just to speak of pooling, if you don’t need sorted object, I should start with an array and not an ArrayList created with the maximum number object you want (if you don’t care about memory ;)). Then use the first part of the array as used objects and the second part as free objects (just use an index to keep that). To add an object, you use have to increase the index. To remove an object, swap in the array the last used object and the object to remove, and decrease the index.
Well it is a really basic one but it works. There is plenty of post about this subject.
The problem is that I don’t know the maximum number because it changes every level. I also don’t have a level cap in place so the levels can go on to infinity… or until your computer runs out of RAM and the program crashes. However it would get so hard by then that it is very unlikely that you would make it that far.
So, it seems that you all agree not to do object pooling in this case. Thanks for the input on my idea, I really appreciate it
I don’t see why you would need to perform any search. When an alien is killed, you will be removing it from the game’s list of aliens. This will happen if you are object pooling or not. If you are object pooling, then you push the alien object onto a stack; no search needed. When you go to make a new object, you check the stack size, pop the top element if it is there, or create a new alien if it is empty; again no search needed.
I also wouldn’t worry too much about memory. You will never get the memory back, unless you clear the object-pool. But lets say the most number of aliens you have on screen at once is 1,000; then you will only have 1,000 persisting in the object pool (when they all die). If you never clear the pool, then you have 1,000 objects sticking around forever. I would expect each Alien object to be relatively small, in terms of memory, and so keeping them around would take up barely any ram. This is only an issue if the alien objects are each holding something large, like if they each have their own unique image.
If memory is an issue, then just clear the pool between levels, or set a cap on how many it will hold at one time.
To implement this in the Alien, you should move the constructor code out from the constructor, and into an ‘initialize’ method. This method wipes the current state, and sets it up as a new, clean Alien. The constructor will call initialize when it is created, and you call initialize when you re-use an Alien object.
When you brake a Java application down into the simple operations you can perform; object-creation is the most expensive (or one of the most expensive) you can do. However I would not expect any real speed difference. You can see a speed difference in applications that continuously make millions, upon millions, of objects. But you will almost certain not be doing this. Your code will probably only be using around 0.1%, so any speed up/down will have no effect at all. What you gain from object-pooling is reducing GC pauses!
So how do you investigate this problem further? First if your game runs smooth, today, then GC pauses is not an issue. If you game is pausing regularly, then it might be caused by the GC, but might not (could be waiting on network/file latency, bad timers, buggy code, etc). The best way to find out if garbage collection is to blame is to profile your application, and watching the memory levels whilst it is running. This will go up as objects are created, and drop when the GC is run. If this is run say once a minute, then it’s nothing to worry about, unless it’s a long pause. If it is run every second, then you should probably do something about it. Next step is to work out what is the cause; which are objects are you creating the most of, and then letting go. To find this out you can more explicitly profile your memory usage, and sort this by number of objects. The best tool you can use for this is the excellent JVisualVM, which comes with the JDK. You’ll find it in the ‘bin’ folder in the JDK’s home on Windows. This is also built into NetBeans, and I would expect Eclipse has these tools as well.
Profiling, to verify the cause of the problem, should be your first port of call.
In my mind, you don’t have to search for object. I supposed that Aliens is deal in a loop something like :
int i =0;
while(i<alienPool.size())
{
Alien alien = alienPool.get(i);
...
if(alien.getLife()<=0)
{
alienPool.remove(i);
}
else
{
...
i++;
}
}
It is a basic example. It doesn’t suit a lot of case. It just to give an idee of how it can be done. That kind of optimization is highly depend of what you need (too complex = loss in performance, too simple = can’t do what you want or even loss in performance).
Even if you get an overall loss in performance from using pooling, it might still be worth it if it eliminates GC stuttering. While experimenting with particles I implemented caching which slowed down the performance a little, but eliminated my huge stuttering problems. Needless to say, I was creating 100.000s of objects per second, not 100. For hundred or even thousand objects, you probably don’t need pooling. Just don’t load stuff like images or textures in your Alien’s constructor.
Premature optimization is never something you should do, if your program runs smoothly on your machine. When it works, then you can begin to optimize, if that’s what you want to do. Make the game first though
I really need to stop optimizing all the time. I obviously keep my code readable, but damn, do I get stuck. Probably the reason why I’ve almost never finished a whole game. I need a deadline or a new attitude to complete my games. :emo:
If you decide to remove from list, use a LinkedList and an Array/HashMap if you decide to not remove from list (as to make access swifter).
Remove from list if you need to loop through list often and/or it’s seldom that all possible aliens are currently alive.
Keep in list if you don’t need to loop through often and/or most of the time the maximum amount of aliens are shown in screen.
If you have to kill many thousands of enemies each loop then I’d suggest what’s earlier suggested in this thread.
Sometimes you need to understand the required optimization as to be able to continue adding features. Refactoring is often the soul of good programming 'cause otherwise the time required to implement each feature will turn exponential.
Though just the kind of optimization he asks about is of course not needed to be implemented at this stage.
[quote]It is a basic example. It doesn’t suit a lot of case. It just to give an idee of how it can be done. That kind of optimization is highly depend of what you need (too complex = loss in performance, too simple = can’t do what you want or even loss in performance).
[/quote]
The get and remove both cause gigantic optimization problems.
Pseudocode I’d recommend if to remove is:
// Clone as to avoid synchronization errors.
// You are not allowed to modify a list you are looping through.
list = alienPool.clone();
for(alien : list){
if(!alien.isAlive()){
alienPool.remove(alien);
}
}
[quote=“Skarion,post:16,topic:37112”]
LinkedList is actually quite slow as it creates an Entry object for each element. It’s slightly faster to just implement your own linked list (as in keeping a reference to the next object). For a list of inactive recycled objects I would use an ArrayList and always remove the last object to avoid an System.arraycopy for the whole array on each remove. This was the fastest I could come up with, but it obviously can’t handle sorting in any way.
Right, I gotta stop drawing that line at “compilable”.
LinkedList is a LOT faster when removing compared to ArrayList (LinkedList just removes the next/past position while ArrayList need to restructure everything). ArrayList is quicker to add.
If problem is that you will have to remove lots of aliens, LinkedList is prefered.
Actually this is a common myth. Random removal from an ArrayList, even though it has to copy the whole array around, is still faster then random removal from a LinkedList. It’s due to the fact that you have to search through the linked list, to find the element to remove, which is much more expensive then using arraycopy. There was a topic on here earlier this year (or last year) where this was discussed in detail.
Removal from the beginning of the list, sure that is faster. But removal of random elements across the whole list, on average, is much slower. Even then there are plenty of tricks to allow array based data-structures out perform linked lists. For example if you are mostly removing from the head, then alter your code to flip how your objects are laid out, so you remove from the end instead. Now the ArrayList becomes much faster again. You can also cache updates, or use lists of arrays to beat the linked list in other corner cases.
Further, very heavy linked list usage will put heavy amounts of stress on the GC. For example if you are using a linked list as the basis for a particle system, then this can cause noticeable stuttering.
The only real advantage of the linked list as a data structure, is if you keep direct references to the nodes in the list, as it allows you to remove then without any searching. You can also do other funky stuff, like swap whole sections of a list, or have the end of one list point into the middle of another, by just altering a couple of references. All (or at least most) of these cannot be efficiently done with java.util.LinkedList. That class is pretty much useless.
You should be removing as often as you’re adding (initial filling of the list aside), so you’re calling each method an equal amount of times. Too bad ArrayList is sooooo unbelievably slow in removing so even though adding to LinkedList is pretty slow, it’s better. (There’s a reason people don’t use ArrayList as a queue, or at least I hope they don’t lol)
But there are better alternatives, like:
public class Entry { // Alien extends Entry
public Entry next;
public Entry last;
}
...
public class ObjectPool<E extends Entry> {
private Entry source;
private Entry last;
public final Entry pop() {
if (source == null)
return null;
Entry e = source;
source = e.next;
return e;
}
public final void add(E e) {
if (source == null) {
source = last = e;
return;
}
last.next = last = e;
}
public final void remove(E e) {
if (e == source) {
source = last = null;
} else if (e == last) {
e.last.next = null;
last = null;
} else {
e.last.next = e.next;
}
}
}
something I threw together quickly, has the bare necessities, almost 2x faster adding than linked list, over 3x faster removing than linked list
(I hope we’re talking in a theoretical situation where you would actually need to use object pooling, and not for this alien game necessarily)