I’m working on my first major game after a lot of failed, smaller projects. But one thing I learned from those projects is to avoid using objects if at all possible for the best performance. I find myself creating bizarre, sparse, multidimensional arrays instead of using classes like ArrayList and HashMap to gain extra fps. Am I being paranoid? I’m using all standard Java libraries and I never have too many performance problems on Windows, but Macs seem to run my games about 60-70% the speed of PCs, so I need the best performance possible.
[quote]I’m using all standard Java libraries and I never have too many performance problems on Windows, but Macs seem to run my games about 60-70% the speed of PCs, so I need the best performance possible.
[/quote]
Tuning for fewer object allocations is barking up the wrong tree. Poor performance on the Mac is caused by the Java2D implementation on Mac OS X, not the machine being slower. Apple is aware of the situation, but has deferred fixing it until Java 5.0 (the version that Sun added the OpenGL pipeline).
In the meantime you can use lwjgl (or jogl for that matter) to get the most drawing speed out of it.
If you only change small sections of the screen (no scrolling) you could also use dirty rectangles (that doesn’t make sense with opengl btw).
If you’re not satisfied with the performance - don’t guess. Profile the application instead. This way you can find the real bottleneck(s).
You could also simply develop using ArrayList and HashMap to keep things simple and clean, but always use its interfaces to reference them (ie don’t reference to ArrayList everywhere but to List).
If, after profiling, the ArrayList turns out to be a bottleneck, implement your own optimized List. I don’t think using List instead of raw arrays pose an inherent performance loss, but your code will be cleaner (which is of course especially important with larger projects).
An ArrayList should be just as fast (for the most part) as a regular array. Using the abstract List interface would be worse, as then you’ve have to use the Iterator methods instead of the familiar for(i etc…) that we all know and love.
But thats probably a red herring. Profile it!
[quote]You could also simply develop using ArrayList and HashMap to keep things simple and clean, but always use its interfaces to reference them (ie don’t reference to ArrayList everywhere but to List).
If, after profiling, the ArrayList turns out to be a bottleneck, implement your own optimized List. I don’t think using List instead of raw arrays pose an inherent performance loss, but your code will be cleaner (which is of course especially important with larger projects).
[/quote]
How is using a reference to an interface going to improve performance?
[quote] Using the abstract List interface would be worse, as then you’ve have to use the Iterator methods instead of the familiar for(i etc…) that we all know and love.
[/quote]
Umm, what about List.get(int) ?
[quote]How is using a reference to an interface going to improve performance?
[/quote]
It’s not. It’s just a way to easily drop in your own optimized List instead of ArrayList later on if necessary, without having to do any refactoring.
I’d recommend rethinking your entire premis; are highlevel data structures ever going to be a bottleneck? Maybe for something like collision detection among thousands of objects but then you should be using a quad/oct/whatever tree anyway.
Thanks for the replies. Since everyone is telling me there must be other problems with my code that have nothing to do with the collection classes I’m using, I will try to profile it and find the bottlenecks. Maybe it’s the way I’m using the collections that is the problem.
I’m also thinking my OOP may be causing performance issues. Whenever I draw something to the screen, my game loop tells the manager class which tells an actor class which tells a sprite class to draw itself. The same thing happens when updating game logic. Maybe I should be more “hands-on” with the graphics context. Well, I guess I should go resign myself to the newbie section for a while.
Don’t feel too bad.
I’ve been doing Java for quite a while now and I still have issues with parts of my code.
OOP isn’t going to cause you ANY performance decrease.
Java has a hotspot compiler and a JIT compiler.
Hotspot compiler will optimise your program when it loads. It will do things like get rid of dead code and inline methods so you will get no performance hit by using getters or setters.
JIT will further improve performance by optimising your code on the fly which will lead to a further performance increase which are dynamic.
There was an article I was reading which stated that coding procedurally will decrease performance.
If you have properly coded in OOP you will see a performance increase over procedural coding.
[quote]Thanks for the replies. Since everyone is telling me there must be other problems with my code that have nothing to do with the collection classes I’m using, I will try to profile it and find the bottlenecks. Maybe it’s the way I’m using the collections that is the problem.
I’m also thinking my OOP may be causing performance issues. Whenever I draw something to the screen, my game loop tells the manager class which tells an actor class which tells a sprite class to draw itself. The same thing happens when updating game logic. Maybe I should be more “hands-on” with the graphics context. Well, I guess I should go resign myself to the newbie section for a while.
[/quote]
I wish we could have parties every now and then where a developer pulls up all their code, everyone profiles it, and everyone searches for things to improve in every aspect of the game I know I could use that myself right now
I found the source of my problem: it wasn’t using objects that was the problem, it was using 1000s of them per second I was creating just a little garbage in my collision detection routine, but that was easily fixed.
I still find it ridiculous how slow Java2D is on the Mac. I’m getting a max of 1200 FPS on my crap 2.4GHz Dell and only about 150 FPS on my 1GHz eMac.
Wrong - hotspot does what you think the JIT does, but hotspot is the JIT.
All code starts interpreted (very slow) and after a method reached a invoke-threshold (in sun-client 1500) it gets compiled to native code.
Sun is currently working on further dynamic imrpovements, but tiger does’nt do any further optimisations on compiled methods.
lg Clemens
Wow, since when is 150 FPS slow?
Interesting. Thanks.
Reading all those articles people have been talking about JIT as a seperate thing from the hotspot compiler.
So it interprets code for a specific amount of time and then enables JIT? Nice.
Well, traditional JITs (as the symantec shipped with jdk12, msjvm) compile all and everything at startup).
What the jvm does at class-loading time are some very simply bytecode-optimizatios, but nothing worth to speak about.
Well, its the best in terms of startup-speed and memory-useage.
One thing which would help this technique would be to save the JIT results (or at least a profile of the last run), but SUN refuses to work on this area steadily - however other VMs creators like Microsoft (with .NET) or BEA (JRockIT) have proofen that this works very well
lg Clemens
[quote]Interesting. Thanks.
Reading all those articles people have been talking about JIT as a seperate thing from the hotspot compiler.
So it interprets code for a specific amount of time and then enables JIT? Nice.
[/quote]
Correct, in the case of the client compiler its 1500, and for the server compiler its 10,000 invocations.
Azeem, while you’re at it, what can I expect of hotspot server if i create a game (say bubbleracer4k) with only one main method (looping indefinitely with a BufferStrategy to paint results) ?
As it would be a unique method call, could it be optimized ?
Lilian
Yes, Hotspot will optimise the bits in the main method that are called repeatedly in loops.
Cas
[quote]Yes, Hotspot will optimise the bits in the main method that are called repeatedly in loops.
Cas
[/quote]
Cas is correct, and depending on how large the methods are that main calls, those will probably get inlined into main as well.