kasemir / org.csstudio.display.builder

Update of org.csstudio.opibuilder.*
Eclipse Public License 1.0
2 stars 10 forks source link

Out-of-memory errors caused by Java FX Canvas #174

Closed kasemir closed 7 years ago

kasemir commented 7 years ago

Plots, including the recently updated data browser, used a Java FX Canvas. The canvas first draws the latest plot image (axes, traces, grid lines, ..) and then optionally adds mouse feedback like crosshair cursor and value markers. In spite of UI updates already being throttled to avoid buildup of redraw requests, the Canvas can result in memory exhaustion because it further buffers drawing requests. A 'draw image' command issued to the Canvas on the UI thread adds that command to an operations lists inside the Canvas which is handled by a scene update thread. In thread dumps taken on memory exhaustion, this queue ('current' variable in Canvas) was found to hold 1000+ references to images which had queued up.

Testing two different workarounds.

a) Monitor the queue and attempt to clear Using Java introspection, obtain a reference to the private GrowableDataBuffer current inside the Canvas as well as the private boolean rendererBehind. As the list of queued operations gets larger, or preventively before every drawImage call, invoke clearRect for the complete canvas which has the side effect of resetting the operations queue ( http://stackoverflow.com/questions/18097404/how-can-i-free-canvas-memory ).

b) Replace Canvas with ImageView Prepare an image that includes mouse feedback and display that in an ImageView.

kasemir commented 7 years ago

Memory usage was similar for an overnight test. Using ImageView seems more straight forward: Certainly just one image passed to the JFX widget, no queue-up. Not depending on side effects of clearRect. Simplifies code because all drawing in AWT, not AWT for axes labels then JFX Canvas GC for 'floating' labels.

kasemir commented 7 years ago

One example after running over night with the same display builder image display and a data browser.

On left, using Cavas with clearRect trick to avoid memory buildup, also skipping updates if rendererBehind is set (which can result in a missing cursor display when mouse move happens to stop in a 'behind' scenario).

On right, using ImageView. No problem with missing the final redraw after mouse moves.

Overall used heap is same, abt. 400MB. In this case, the canvas setup kept the overall heap size at 1GB for some internal reason, while the ImageView setup shrunk the heap size to be just above the used heap.

canvas_vs_image3

kasemir commented 7 years ago

After running for several days, again no memory leak. The version based on ImageView (right) consistently uses less memory.

canvas_vs_image