maptool icon indicating copy to clipboard operation
maptool copied to clipboard

[Refactoring]: Noticeable performance regression with lights in 1.12

Open kwvanderlinde opened this issue 1 year ago • 0 comments

Describe the problem

Light rendering has become significantly slower in some cases in the 1.12 alpha than it was in 1.11.5. This is usually not very noticeable when doing things like just dragging a token, but can make for a noticeable difference when lights have to be rerendered many times (e.g., if a token is being animated).

While some performance loss may be expected due to our customized light blending and new darkness overlay, testing shows that the loss is primarily time taken to render the overlay buffers to the swing-provided Graphics object, while hardly any time is spent rendering the lights/auras to the buffers.

The improvement you'd like to see

The light overlays in ZoneRenderer (or maybe all of ZoneRenderer) would all be rendered to a temporary BufferedImage buffer. Then that single buffer would be drawn to the swing-provided Graphics object. Also, if there are no lights or auras we should avoid drawing the buffers.

Expected Benefits

In cases like mine, we could probably shave off ~75% of the rendering time for lights/auras, and reduce the trivial case of no lights or auras to basically nothing as it was before.

Additional Context

For some comparision, I did my testing on my desktop Linut Mint 20.3, Intel Core i5-9400, NVidia GTX 1050. I've tried a couple of other rigs as well (a newer AMD laptop for instance and a much older desktop) and results so far are pretty consistent.

The specific case I am noticing the slowdown is where a map contains some VBL and a single light-equipped token. The token is being made to constantly move via macros. This is the only light source present, there are no auras or darkness sources, and FoW is disabled. I will pull out this test case into something convenient for others as its currently embedded in a much larger campaign file.

Here's some preliminary numbers from the ZoneRenderer.renderZone timer on 1.11.5:

  • The lights timing almost always measures 0 ms, though now and then it can spike to 5 ms worst case.
  • The auras timing is always 0 ms (no auras to render == really quick)

By contrast, on 1.12.0 alpha 1 I set:

  • The lights timing settles to ~15 ms (as low as 10 ms, as high as 20 ms, and sometimes can go crazy up to ~45 ms)
  • The auras timing is consistently between 6ms and 11ms despite having no auras to render.

From experimentation I found that drawing one BufferedImage onto another is quite cheap (~1ms typically) while rendering a BufferedImage to the screen is quite expensive. On a hunch, I also tried enabled OpenGL rendering for MapTool, which completely eliminates the performance penalty with rendering BufferedImages to the screen. Unfortunately, it also comes with some other rendering issues, which is why I'm not proposing that as a solution. However, it leads me to believe that drawing onto a BufferedImage is more akin to OpenGL-enabled rendering than drawing straight to the screen.

kwvanderlinde avatar Aug 03 '22 04:08 kwvanderlinde