Tora said:
Also that may be of interest to you:
Tuning Garbage Collection with Java 5.0 VM
Yep. Thanks. I was actually reading that and trying various settings earlier today. So far not luck.
Tora said:
Also that may be of interest to you:
Tuning Garbage Collection with Java 5.0 VM
Tora said:
Try to not to call repaint() inside setText().
Anyway, we don't know what else you've got on your code. If you do a setText() at 500fps for example, you're creating 500 strings per frame, thats a lot of strings ;)
There could be a lot of things involved. But you can isolate the problem by removing parts of your ui. For example, don't update any label. If the blocking persists, probably it was something else, so try stop updating any other things until you find out what was causing the problem.
We could help you better if you could provide some 'test case' to show us. A small application doing something that presents the same symptons as your full application.
Edit: As Llama said before, the 'desktop' JMEDesktop shows is a texture. That needs to be recreated each time something changes. And loaded into video memory. That's expensive, very expensive ;) One thing you can do to check if it's that, is to create your JDesktop as a usual swing JDesktop, not being rendered inside the opengl window but as a normal swing frame.
Hi!
Call repaint somewhere else, not inside the component. Thats what I wanted to say
I'm not sure right now about the fixed logic rate application base, but if your logic is updating at 20fps, why would you need your display being refreshed at a higher frame rate? Nothing should change on your display unless something changed on your logic. Methinks.
Made a quick test using the examples, and adding 30 labels. Updating them all causes horrible things XD Just updating four of them still is ugly.
So my final advice is: Don't use JMEDesktop for that purpose.
I think Llama had the answer, too much texture processing on each frame. That along the swing things is just a killer for the performance.
I don't believe there's a solution, swing designers didn't focus on that use and the texture thing is just as is. So looks like you have to implement your own 3d labels using the jme text classes, or maybe using one of the other ui implementations for jme as bui or nui.
Looking at what you posted first, seems that you don't use any decorations on your labels, just the 'plain text' with no borders or backgrounds. So using the text classes provided by jme to render text on screen seems to fit. If you don't like the font, you can use another
Sorry for not finding a way to solve this using swing. I'm out of ideas now.
Interesting. I would have to agree with you that the problem is in painting, because yesterday when I wasn't repainting and the values where changing slowly I didn't see the problem. Whenever I repainted whenever the value was changed (every 20th of a second), I started seeing the problem. Anyway, I did your test and the values were pretty much like this:
updated: 316:282
updated: 251:22
updated: 316:282
updated: 316:22
updated: 251:22
So I reduced the size of the text fields down to about 34:22 and the problem occured about that much less proportionally. It still happens, just far more infrequently.
The reason you probably didn't see much of a performance hit with typing fast is that it seems to be worse when several components are being repainted. If it's just one component, then I don't really see the problem (from what I can tell). Unless in that case I'm just seeing the problem so much less that it only occurs every 10 minutes and I'm not testing long enough.
Here's the thing that miffs me. I played around with all kinds of gc settings so it would try to gc more frequent, but faster collections and it still stuttered when it finally decided to jettison the swing garbarge. Am I missing someething or is that not the crux of the problem?
I assume the size of your label that holds the value your are changing is smaller than 316:282 pixels. So the question is, what more is repainting and why?
After all, why would it be different if I type a value in a textfield (the whole texfield gets repainted), or if you use
speedText.setText(ship.getCurrentSpeed() + "m/s");
Good golly miss molly. I must be tired this morning to have missed that. Well, I checked and I definitely do not have a text field that large. What I see happening is for every 7 setText calls (the number of text fields being updated during each iteration) there is one call to LWJGLImageGraphics update(). In most cases it is printing "updated: 316:22" but then (and sometimes this is every other call) it gives "updated: 316:282". The only thing I can think of is that this is the total extent of all the updated text components as they are grouped into an area of about 316x282. To my knowledge the size of the fields are definitely not changing. They are all fixed at 247x18.
I'm even more puzzled now.
BTW, I pulled all these variable declarations out of their methods to cut down on the gc. It seems to have helped the situation, but not completely eliminated it.
private ByteBuffer scratch;
private ByteBuffer tempData;
private boolean updateChildren;
private boolean hasMipMaps;
private int dx1;
private int dy1;
private int dx2;
private int dy2;
private int dw ;
private int dh;
private Composite composite;
I can post the whole class if you think these changes should be checked in.
Aaah, so you have several textfields you are updating each frame? Here I was being all puzzled why one tiny textfield could be making everything to slow
Maybe you can use one textfield total (using linefeeds)?
A wild suggestion…
Why not handle all the text you want to print in just one single JComponent?
That is, implementing a 'multitext label', which may have something like this:
setText(int index, String text);
and paint every text you set on it's paint method, arranging it by yourself, so you can also get rid of layout managers.
llama said:
Aaah, so you have several textfields you are updating each frame? Here I was being all puzzled why one tiny textfield could be making everything to slow :)
Maybe you can use one textfield total (using linefeeds)?
Tora said:
A wild suggestion....
Why not handle all the text you want to print in just *one* single JComponent?
That is, implementing a 'multitext label', which may have something like this:
setText(int index, String text);
and paint every text you set on it's paint method, arranging it by yourself, so you can also get rid of layout managers.
Just to clarify. If you wanted a test case, I'm sure if you put just two tiny JTextFields, say containing just one number, with one component in the upper left corner of the screen and one in the lower right corner, and then updated them regularly, you'd probably have a pretty severe problem because it would be rendering a 1280x1024 (or whatever size your screen is) texture.
Updating a texture with OpenGL should slow your framerate, but not create stuttering (at least not due to garbage collecting). Do you still have actual stuttering, and do you still see spikes in the GC view? If so, where does the garbage come from?
Like I said, the BufferedImage -> Texture uploading process is not that great. The awtImage.getRaster().getDataElements( dirty.x, dirty.y, dirty.width, dirty.height, data ) in particular seems slow. So we could try and optimize that, but if you still get random stuttering every 5/10 seconds, that's of little use.
For example, I wrote a video-to-texture package for jME that updates things like a 640x480 texture 30 times a second (using the same OpenGL method at LWJGLImage), without much problems. You still have plenty CPU left, even after decoding the video stream.
Something that could help:
jmeDesktop.getJDesktop().setDebugGraphicsOptions(DebugGraphics.LOG_OPTION|DebugGraphics.BUFFERED_OPTION);
The stuttering is maybe a bit more infrequent that 5-10 seconds now. It happens say every 45-60 seconds when the big gc kicks in. I wish I had a better grasp of YourKit to analyze the gc. Would it be helpful if I sent you a snapshot of memory?
I turned on the debugging and this is what I got for one frame. Seems like a bit of redundant stuff going on. And why is it constantly setting the font and color? I guess I just don't understand the low level workings of Swing.
Graphics(34027-5) Enabling debug
Graphics(34027-5) Setting color: sun.swing.PrintColorUIResource[r=51,g=51,b=51]
Graphics(34027-5) Setting font: javax.swing.plaf.FontUIResource[family=Dialog,name=Dialog,style=plain,size=12]
Graphics(34029-5) Setting color: java.awt.Color[r=0,g=0,b=0]
Graphics(34029-5) Filling rect: java.awt.Rectangle[x=0,y=0,width=1280,height=1024]
Graphics(34031-5) Setting color: java.awt.Color[r=110,g=110,b=110]
Graphics(34031-5) Setting font: java.awt.Font[family=Arial,name=arial,style=bold,size=16]
Graphics(34031-5) Setting color: java.awt.Color[r=110,g=110,b=110]
Graphics(34031-5) Setting font: java.awt.Font[family=Arial,name=arial,style=bold,size=16]
Graphics(34033-5) Setting color: java.awt.Color[r=110,g=110,b=110]
Graphics(34033-5) Drawing string: "5037m" at: java.awt.Point[x=0,y=15]
Graphics(34034-5) Setting color: java.awt.Color[r=110,g=110,b=110]
Graphics(34034-5) Setting font: java.awt.Font[family=Arial,name=arial,style=bold,size=16]
Graphics(34034-5) Setting color: java.awt.Color[r=110,g=110,b=110]
Graphics(34034-5) Setting font: java.awt.Font[family=Arial,name=arial,style=bold,size=16]
Graphics(34036-5) Setting color: java.awt.Color[r=110,g=110,b=110]
Graphics(34036-5) Drawing string: "0m/s" at: java.awt.Point[x=0,y=15]
Graphics(34037-5) Setting color: java.awt.Color[r=110,g=110,b=110]
Graphics(34037-5) Setting font: java.awt.Font[family=Arial,name=arial,style=bold,size=16]
Graphics(34037-5) Setting color: java.awt.Color[r=110,g=110,b=110]
Graphics(34037-5) Setting font: java.awt.Font[family=Arial,name=arial,style=bold,size=16]
Graphics(34039-5) Setting color: java.awt.Color[r=110,g=110,b=110]
Graphics(34039-5) Drawing string: "880m" at: java.awt.Point[x=0,y=15]
Graphics(34040-5) Setting color: java.awt.Color[r=110,g=110,b=110]
Graphics(34040-5) Setting font: java.awt.Font[family=Arial,name=arial,style=bold,size=16]
Graphics(34040-5) Setting color: java.awt.Color[r=110,g=110,b=110]
Graphics(34040-5) Setting font: java.awt.Font[family=Arial,name=arial,style=bold,size=16]
Graphics(34042-5) Setting color: java.awt.Color[r=110,g=110,b=110]
Graphics(34042-5) Drawing string: "0m/s" at: java.awt.Point[x=0,y=15]
updated: 199:22 - 487.0, 335.0
BTW, for this test I reverted to using JLabel for the text.
Yes, seems that swing does a lot of work for painting a single label
I've tried 30 custom labels, with the following parameters on the jvm:
-XX:+UseParallelGC
-Xoptimize
-XX:+DisableExplicitGC
-XX:+UseBiasedLocking
-XX:+UseParallelOldGC
-XX:+AggressiveOpts
-Xms128M
-Xmx128M
Now I've got a stable 30-36 fps, it doesn't stutter. Without doing the text setting was 400-500 fps, so it's not really that great XD
Improved the frame rate to ~120fps!
Instead of calling repaint on each label, I called the repaint on the panel from the interfal frame:
internalFrame.getContentPane().repaint();
Tora said:
Improved the frame rate to ~120fps! :D
Instead of calling repaint on each label, I called the repaint on the panel from the interfal
The labels are inside a JInternalFrame. Instead of calling repaint() on each label, I call repaint() on the JInternalFrame.
Not sure how did you arrange the components, but if its different, try calling 'repaint' on their parent component. Or maybe on the parent of the parent component