Closed tiehfood closed 3 years ago
Hello,
Thank you for your interesting observations. What OS and java version are you using?
I haven't worked with VolatileImage. Would you be interested in sharing your code? I'd like to compare it to the current version.
Many thanks, -Jeremy
All in SOCBoardPanel
Starting with loadHexesAndImages
newHexes[0] = ImageIO.read(clazz.getResource(imageDir + "waterHex.png"));
newHexes[1] = ImageIO.read(clazz.getResource(imageDir + "clayHex.png"));
newHexes[2] = ImageIO.read(clazz.getResource(imageDir + "oreHex.png"));
newHexes[3] = ImageIO.read(clazz.getResource(imageDir + "sheepHex.png"));
newHexes[4] = ImageIO.read(clazz.getResource(imageDir + "wheatHex.png"));
newHexes[5] = ImageIO.read(clazz.getResource(imageDir + "woodHex.png"));
newHexes[6] = ImageIO.read(clazz.getResource(imageDir + "desertHex.png"));
getScaledImageUp
public static final BufferedImage getScaledImageUp(final BufferedImage src, final int w, final int h)
{
BufferedImage buff = gfxConfig.createCompatibleImage(w, h, Transparency.BITMASK);
Graphics2D g = bufi.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.drawImage(src, 0, 0, w, h, null);
g.dispose();
return bufi;
}
drawBoard
VolatileImage ebb = emptyBoardBuffer;
if (scaledMissedImage || ebb == null)
{
if (ebb == null)
{
ebb = gfxConfig.createCompatibleVolatileImage(scaledPanelW, scaledPanelH);
emptyBoardBuffer = ebb;
}
drawnEmptyAt = System.currentTimeMillis();
scaledMissedImage = false;
drawBoardEmpty(ebb.createGraphics());
if (scaledMissedImage && (scaledAt != 0) && (RESCALE_MAX_RETRY_MS < (drawnEmptyAt - scaledAt)))
scaledMissedImage = false;
}
g.setPaintMode();
g.drawImage(ebb, 0, 0, this);
...
paintComponent
VolatileImage ibuf = buffer;
try
{
if (ibuf == null)
{
ibuf = gfxConfig.createCompatibleVolatileImage(scaledPanelW, scaledPanelH);
buffer = ibuf;
}
try
{
drawBoard(ibuf.createGraphics());
} catch (ConcurrentModificationException cme) {
repaint();
return;
}
...
of corse you have to change all your variables from type Image to BufferedImage
P.S. I'm using it on MacOS (java RE 1.8) and Windows (JDK 1.8/11)
Thank you, I will take a look soon.
A little cosmetic tuning: I created a static variable icon for SOCPlayerClient with the official JSettlers icon image and then called on each new frame setIconImage . This way I have the nice official icon (i.e. on windows) and not the ugly default java icon. Don't know if it's the best way with the static variable in SOCPlayerClient, but it works 😊
Thanks @tiehfood , I've written some optimization code based on the docs and our discussion here. Tested on java 8 and newer on various platforms, including with stand-in big PNG images.
When you have time, could you please check out my feat/boardpanel-perf-84
branch to see if that works for you? If it looks good, I'll merge to master.
Thank you!
I only did a short test but as far as I could tell it looks very good. CPU usage drops to about 1/3 or even 1/4 in the new version while moving the mouse/resizing the board :)
You could also implement the BufferedImages on the player icons. Not that big impact on performance but would be consistent across image handling
This is a great improvement, thank you again :)
I'll consider this done, and I'll update the todo list with your other suggestion.
I use my own hex tile set with JSettlers2. As the images have a higher resolution than the default ones, I experienced a very high CPU usage while playing a game. To optimize performance I fist changed all of the GIF files to PNGs, which performed much better on my machine. Then I changed all the image processing and handling from Image to BufferedImages. For drawBoard and drawBoardEmpty I used VolatileImages instead. With this changes, the game uses drastically less CPU with my custom tile set.