maptool
maptool copied to clipboard
[Refactoring]: Noticeable performance regression with lights in 1.12
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 BufferedImage
s 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.