Runnable, RunnableLock instances accumulating on asyncExec [message #1731265] |
Tue, 03 May 2016 23:07  |
Eclipse User |
|
|
|
I'm still trying to get into SWT, so maybe that's a beginner question:
I'm working on a time domain plot using Canvas. I implemented this component using JavaFX, Swing and SWT because we have performance issues with JavaFX.
The data gets updated faster than the canvas is able to repaint. So, in Swing I do the following:
// ...
SwingUtilities.invokeLater(() -> updateView(data));
void updateView(GraphData data) {
this.currentGraphData = data;
this.repaint();
}
This works nicely and it's also performant enough.
A similar approach for my SWT component:
// ...
this.getDisplay().asyncExec(() -> updateView(data));
void updateView(GraphData data) {
if (!this.isDisposed()) {
this.currentGraphData = data;
this.redraw();
}
}
This works also nicely, although it seems to be a bit less performant. However it looks like I had a memory leak, because heap space increases over time. This is caused by org.eclipse.swt.widgets.RunnableLock and the Runnable itself accumulating. I'll get a constant heap consumption when I use syncExec instead of asyncExec, unfortunately this pauses the background thread which I don't want to happen.
So my question: is there a way to check if the UI thread is too busy, crowded, etc. to be able to throw some of the updates away? I assume this is what Swing does under the hood, because heap space consumption goes up and down massively, but it never piles up.
Cheers,
Andy
|
|
|
Re: Runnable, RunnableLock instances accumulating on asyncExec [message #1731281 is a reply to message #1731265] |
Wed, 04 May 2016 02:57   |
Eclipse User |
|
|
|
Seems to be a flood of the SWT messages queue.
Maybe, you could exec the draw operation delayed using Display.timerExec()
If you would use 16 ms as delay, you would still get 60 frames/second.
Andy Junius wrote on Wed, 04 May 2016 05:07I'm still trying to get into SWT, so maybe that's a beginner question:
I'm working on a time domain plot using Canvas. I implemented this component using JavaFX, Swing and SWT because we have performance issues with JavaFX.
The data gets updated faster than the canvas is able to repaint. So, in Swing I do the following:
// ...
SwingUtilities.invokeLater(() -> updateView(data));
void updateView(GraphData data) {
this.currentGraphData = data;
this.repaint();
}
This works nicely and it's also performant enough.
A similar approach for my SWT component:
// ...
this.getDisplay().asyncExec(() -> updateView(data));
void updateView(GraphData data) {
if (!this.isDisposed()) {
this.currentGraphData = data;
this.redraw();
}
}
This works also nicely, although it seems to be a bit less performant. However it looks like I had a memory leak, because heap space increases over time. This is caused by org.eclipse.swt.widgets.RunnableLock and the Runnable itself accumulating. I'll get a constant heap consumption when I use syncExec instead of asyncExec, unfortunately this pauses the background thread which I don't want to happen.
So my question: is there a way to check if the UI thread is too busy, crowded, etc. to be able to throw some of the updates away? I assume this is what Swing does under the hood, because heap space consumption goes up and down massively, but it never piles up.
Cheers,
Andy
|
|
|
|
Re: Runnable, RunnableLock instances accumulating on asyncExec [message #1731396 is a reply to message #1731265] |
Wed, 04 May 2016 19:19  |
Eclipse User |
|
|
|
OK, I found a solution; maybe not the best one, but it certainly does the job:
// control flag
volatile boolean updateRunning = false;
// gets called on model updates
public void setCurrentGraphData(GraphData data) {
new Thread(new UpdateCanvas(data)).start();
}
// this requests the actual redraw
void updateView(GraphData data) {
if (!this.isDisposed()) {
this.currentGraphData = data;
this.redraw();
}
}
private class UpdateCanvas implements Runnable {
private final GraphData data;
UpdateCanvas(GraphData data) {
super();
this.data=data;
}
@Override
public void run() {
if(!updateRunning) {
updateRunning = true;
getDisplay().syncExec(() -> updateView(data));
updateRunning = false;
}
}
}
Heap space consumption is now a lot less than the one of the Swing component and it's constant. I'll finally have to reduce the amount of updates, but this was a very nice exercise.
Cheers,
Andy
|
|
|
Powered by
FUDForum. Page generated in 0.13907 seconds