Java awt performance anxiety
There is a program that generates hundreds or thousands of moving particles onscreen at once. After several hundred are displayed, slowdown occurs. Performance was analyzed using netbeans profiler and about 80% of the time was spe开发者_如何学Pythonnd in the jpanel's paint method...so algorithm optimization seems unlikely to make a noticeable difference. Is there anything that can be done about this or is it time to think about a new platform? The paint method looks something like this:
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(Color.WHITE);
for (int i = 0; i < gameLogic.getParticleArrSize(); i++) {
g.setColor(gameLogic.getParticleColor(i));
g.fillOval(gameLogic.getParticleXCoor(i),
gameLogic.getParticleYCoor(i),
gameLogic.getParticleSize(i),
gameLogic.getParticleSize(i));
}
g.setColor(gameLogic.getCurrPartColor());
g.fillOval(mouseX - mouseOvalRadius, mouseY - mouseOvalRadius,
mouseOvalSize, mouseOvalSize);
g.setColor(gameLogic.getCursorColor());
g.fillOval(mouseX - 19, mouseY - 19, 38, 38);
for (int i = 0; i < gameLogic.getBombArrSize(); i++) {
g.setColor(Color.RED);
g.fillOval(gameLogic.getBombXCoor(i) - 6,
gameLogic.getBombYCoor(i) - 6,
gameLogic.getBombSize(i),
gameLogic.getBombSize(i));
}
for (int i = 0; i < gameLogic.getPowerUpParticleArrSize(); i++) {
g.setColor(gameLogic.getPowerUpParticleColor(i));
g.fillOval(gameLogic.getPowerUpParticleXCoor(i),
gameLogic.getPowerUpParticleYCoor(i),
gameLogic.getPowerUpParticleSize(i),
gameLogic.getPowerUpParticleSize(i));
}
for (int i = 0; i < gameLogic.getBlackArrSize(); i++) {
g.setColor(Color.BLACK);
g.fillOval(gameLogic.getBlackParticleXCoor(i),
gameLogic.getBlackParticleYCoor(i),
gameLogic.getBlackParticleSize(i),
gameLogic.getBlackParticleSize(i));
}
}
When are you triggering repaint()? Is it set on a timer on some time interval? I created an animation lib and I was able to animate 40 items smoothly. You probably have many more objects but I would look at the time interval first.
Edit: Ok so here is my suggestion. First you need to figure out which function in paint is taking the most amount of time. It seems like you are calling fillOval a lot. My suggestion would be to create the shape once using something like: new RoundRectangle2D.Double(). And then use AffineTransformation to move around the shapes instead. I am curious to know what other suggest, so I will check back.
Try exploring the Graphics2D library. The fill algorithm for any shape, even something as simple as an oval, is expensive. It is far faster to create a shape, fill it then copy it to other locations. The 2D library also supports various transforms for scaling etc.
This is very similar to Daniel Viona's sprite suggestion. Sprites exist for a reason - they are a fast way to draw many small simple objects!
If I get some time I will try to draw 1000's of small objects - care to give an idea of the size range these objects will have? Just a few pixels? I am guessing the power ups and bombs are relative few, it is only the particles that are hurting you right...
about 80% of the time was spend in the jpanel's paint method
Since the vast majority of your processing is single-threaded, that means at least one CPU core is being almost entirely wasted on modern machines. Most computers have at least dual-cores these days, if not more. There are a couple ways for you to take advantage of this:
- If 80% of your time is spent in one method, make sure that the remaining 20% doesn't have to wait for the painting to complete. Compute the next frame in advance while waiting for the last one to finish drawing.
- Your paint method can also be split up into multiple threads. It's not safe to share the same Graphics object between multiple threads, but you can have different threads rendering to different images then composite them together at the end.
- For example, have one thread take the first half of the particles and render directly to the backbuffer. A second thread takes the remaining particles and renders them to an image. Once they both complete, blit the image to your backbuffer, combining the two images.
As a bonus note... If you really want performance, consider JOGL. Look here for an example:
- http://download.java.net/media/jogl/jsr-231-2.x-demos-webstart/ParticleEngine.jnlp
精彩评论