Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Performance regression for lights/sights performance on 1.12.0 #3651

Closed
kwvanderlinde opened this issue Sep 21, 2022 · 15 comments · Fixed by #3666
Closed

[Bug]: Performance regression for lights/sights performance on 1.12.0 #3651

kwvanderlinde opened this issue Sep 21, 2022 · 15 comments · Fixed by #3666
Assignees
Labels
bug performance A performance or quality of life improvement tested This issue has been QA tested by someone other than the developer.

Comments

@kwvanderlinde
Copy link
Collaborator

kwvanderlinde commented Sep 21, 2022

Describe the Bug

Map rendering on 1.12.0 can be choppy even with only a handful of sights or lights in play if they take up a signification portion of the viewport.

To Reproduce

  1. Open the performance logs (Tools > Collect Performance Data)
  2. Open this campaign: slow-sights.cmpgn.renamedto.zip
  3. Go to either the "Several sights" or "Several lights" map.
  4. Zoom in a bit to make the lights together take up the entire screen.
  5. In the performance logs, under ZoneRenderer.renderZone, observe high paintComponent times , and in particular high renderLightOverlay:drawLights times.

Expected Behaviour

The map can be rendered smoothly in the presence of a few lights or sights (<16 ms or so).

Screenshots

This screenshot shows that it can easily happen that a viewport fills with sights or lights even when only the party is on the map, and at reasonable zoom levels:
image

MapTool Info

1.12.0

Desktop

Linux Mint 21

Additional Context

This is a performance regression since 1.11.5 and is related to the implementation of additive lights (#1550). The times I am seeing are 50-60 ms or more for drawing lights, and sometimes as high as 80ms for rendering the zone.

I am running two monitors both at 2560x1440, though MapTool is constrained to just one monitor. If I reduce this to 1920x1080 it's a much better experience, but still 25-30 ms per render.

Debug information
==== MapTool Information ====
MapTool Version: 1.12.0
MapTool Home...: /home/kenneth/.maptool-rptools
MapTool Install: /opt/maptool/lib/app
Max mem avail..: 5 GB
Max mem used...: 476 MB
Custom Property: -DMAPTOOL_LOGDIR=/home/kenneth/.maptool-rptools/logs
Custom Property: -DMAPTOOL_DATADIR=.maptool-rptools

==== Java Information ====
Java Home......: /opt/maptool/lib/runtime
Java Vendor....: Eclipse Adoptium
Java Version...: 17.0.1
Java Parameters:
-Djpackage.app-version=1.0
-Xss8M
-Dsun.java2d.d3d=false
-Dsentry.environment=Production
-Dfile.encoding=UTF-8
-Dpolyglot.engine.WarnInterpreterOnly=false
-XX:+ShowCodeDetailsInExceptionMessages
--add-opens=java.desktop/java.awt=ALL-UNNAMED
--add-opens=java.desktop/java.awt.geom=ALL-UNNAMED
--add-opens=java.desktop/sun.awt.geom=ALL-UNNAMED
--add-opens=java.base/java.util=ALL-UNNAMED
--add-opens=javafx.web/javafx.scene.web=ALL-UNNAMED
--add-opens=javafx.web/com.sun.webkit=ALL-UNNAMED
--add-opens=javafx.web/com.sun.webkit.dom=ALL-UNNAMED
--add-opens=java.desktop/javax.swing=ALL-UNNAMED
--add-opens=java.desktop/sun.awt.shell=ALL-UNNAMED
--add-opens=java.desktop/com.sun.java.swing.plaf.windows=ALL-UNNAMED
-Djpackage.app-path=/opt/maptool/bin/MapTool

==== OS Information ====
OS Name........: Linux
OS Version.....: 5.15.0-47-generic
OS Architecture: amd64
PATH...........: /home/kenneth/.local/bin:/home/kenneth/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/kenneth/.local/share/JetBrains/Toolbox/scripts
Number of Procs: 6

==== User Information ====
User Name: kenneth
User Home: /home/kenneth
User Dir.: /home/kenneth

==== Network Interfaces ====
Display Name..: ztzlgjggbh
Interface Name: ztzlgjggbh
Address...: fe80:0:0:0:44f6:e7ff:fecd:96b%ztzlgjggbh
Address...: 10.144.224.214

Display Name..: zthnhauxdb
Interface Name: zthnhauxdb
Address...: fe80:0:0:0:547f:6fff:fe98:c47a%zthnhauxdb
Address...: 10.147.18.47

Display Name..: zt44xpuk3a
Interface Name: zt44xpuk3a
Address...: fe80:0:0:0:cd4:7eff:fec1:189b%zt44xpuk3a
Address...: 10.147.17.47

Display Name..: wlp4s0
Interface Name: wlp4s0
Address...: 2001:569:5585:1900:9f80:165c:409d:3050%wlp4s0
Address...: fe80:0:0:0:ce3c:aef8:5ac:aca6%wlp4s0
Address...: 2001:569:5585:1900:14dd:248a:b63b:fabc%wlp4s0
Address...: 192.168.1.74

Display Name..: lo
Interface Name: lo
Address...: 0:0:0:0:0:0:0:1%lo
Address...: 127.0.0.1

Host Address...: 127.0.1.1
Default Gateway: 192.168.1.254

==== Locale Information ====
Country.: Canada
Language: English
Locale..: English (Canada)
Variant.:

==== Encoding Information ====
Default Locale: en_CA
Default Charset: UTF-8
file.encoding: UTF-8
sun.jnu.encoding: UTF-8
Default Encoding: UTF8

==== Display Information ====
Number of Displays: 2
Display 1: 5120x1440(-1)
Display 2: 2560x1440(-1)

==== Internet Gateway Devices ====
Device Name.: Actiontec xDSL Router
Model Name..: T3200M
Manufacturer: Actiontec
Model Number: 1.0
Model Desc..: (null)
Firmware....: Custom/1.0 UPnP/1.0 Proc/Ver
External IP.: 162.156.118.146

@kwvanderlinde kwvanderlinde added bug performance A performance or quality of life improvement labels Sep 21, 2022
@cwisniew
Copy link
Member

@kwvanderlinde it might be worth testing with different scaling qualities (preferences -> application ) to see if there is any interaction there as this also affects the rending hints for different things being drawn to the buffer.

@kwvanderlinde
Copy link
Collaborator Author

Even at lowest quality the issue persists. I've also tried reverting that particular change altogether and light rendering remains just as slow.

@kwvanderlinde
Copy link
Collaborator Author

One thing I noticed is that the repeated Graphics2D::setPaint() calls are surprisingly costly. In this test case, if we only make the call it once for all sights (they are all the same after all) then the renderLightOverlay:drawLights times drop to only 30ms for a typical render (still too high of course, but at least better). The nice thing about our screen/multiply blends is that they are order independent, so we should be able to group lights by paint for a potential improvement in the case of repeated sights/lights.

Beyond that, I have spent a fair amount of time trying to figure a way to improve the performance of drawing the lights themselves. Unfortunately, every idea I get has come up short and I've never been able to get a consistent improvement. So if anyone has some thoughts I would love to hear them.

@cwisniew
Copy link
Member

cwisniew commented Sep 21, 2022

So given I can't currently look at the code but if you are willing to entertain thoughts....

If we are rendering lights with blending modes to the same buffer then drawing that into the map it might be more efficient to render each light to its own buffer without any blending mode, then in one pass draw all those buffers into another with blending on. Drawing a rectangle with blending is more easily optimised than filling an arbitrary shape with blending. But the questions are 1) Is it optimised in the Java2d Graphics library, 2) is the speed difference enough to make up for the increased number of pixels you are drawing :) Oh and I guess 3) is it an easy enough thing to change to test that if it doesn't work its not a lot of time lost.

@kwvanderlinde
Copy link
Collaborator Author

That was a good idea, unfortunately it didn't yield any improvements. It did at least give out BlendingComposite the best possible chance by having it operate on an entire rectangle rather than a bunch of lines. But even so it turns out the work being done in BlendingComposite completely overshadows any overhead from J2D and - it turns out - the extra work of doing more image-on-image drawing.

Looks like I really do need to come up with a way of speeding up BlendingComposite itself. But looking around at other implementations of the same concept, they all look pretty similar and ours is actually one of the faster ones at the cost of less generality.

@cwisniew
Copy link
Member

cwisniew commented Sep 22, 2022

I took a look at the BlendingComposite code and I can't see an obvious way to improve it a great deal without resorting to using the vector API or rendering off-screen in LWJGL. I pick LWJGL over JOGL as libGDX uses LWJGL as it would require fewer changes to work with with #3468 (which is still probably some time away). The latter I guess is not really improving BlendingCompoiste but replacing it :)

Another thing you can do that may help in the general case is a bounding box check to see which light sources overlap that generates "list of lists" of light sources that overlap. And if you can cache them and only have to compare lights that have moved even better.
You can safely draw the first light in each list without having to worry about composite blending.
Bounding box comparisons should be much faster than a composite render.

  • In the best case where there are no overlapping lights it would eliminate all usages of BlendingComposite
  • In the worst case you only eliminate only one of the composite renders and there will be a point where the bounding box checks take longer than you save on that single render.

I guess it then comes down to the different usages.

  • In a party where everyone has lights it's going to tend towards the worst case every time
  • In a party with one light and lights dotted all over the map then there is potential to save quite a bit of time.

@kwvanderlinde
Copy link
Collaborator Author

I am looking forward to one day having a libGDX renderer as that would open up an avenue for lots of neat things.

Your idea of grouping lights is interesting and that would allow us to rescue performance in cases of isolated lights. But the point of the additive blending feature is to make overlapped lights look better, and I am finding that even a couple of overlapped lights are enough to cause performance to noticeably suffer. And I'm not exactly running this on a low-end system, so I can only imagine what some other users will run into.

I'm honestly thinking it might be better to pull the feature for the time being until we have something like the libGDX renderer that could support more interesting effects.

@Phergus
Copy link
Contributor

Phergus commented Sep 23, 2022

Is this the kind of slow-down you are seeing?
image

@kwvanderlinde
Copy link
Collaborator Author

Yeah that's it.

@kwvanderlinde
Copy link
Collaborator Author

Another thing we could do is - similar to the image scaling - have a lighting quality preference that can either use BlendingComposite (for those with beefy CPUs or who don't mind the lagginess) or else fallback to the more performant AlphaComposite (similar to lighting in 1.11.5, but with lights of the same colour also blending together).

@FullBleed
Copy link

I am looking forward to one day having a libGDX renderer as that would open up an avenue for lots of neat things.

Your idea of grouping lights is interesting and that would allow us to rescue performance in cases of isolated lights. But the point of the additive blending feature is to make overlapped lights look better, and I am finding that even a couple of overlapped lights are enough to cause performance to noticeably suffer. And I'm not exactly running this on a low-end system, so I can only imagine what some other users will run into.

I'm honestly thinking it might be better to pull the feature for the time being until we have something like the libGDX renderer that could support more interesting effects.

Have you looked into the issues that are going on with libGDX in MT? Getting that thing working with MT could probably use a wizard like you in the mix. ;) I don't want to speak for him (but I guess I kinda am), but right now it seems like @thelsing is only touching it on occasion and could use some help.

@cwisniew
Copy link
Member

Have you looked into the issues that are going on with libGDX in MT? Getting that thing working with MT could probably use a wizard like you in the mix. ;) I don't want to speak for him (but I guess I kinda am), but right now, it seems like @thelsing is only touching it on occasion and could use some help.

To my understanding, the LibGDX port is still incomplete and there as there is functionality that is not yet implemented. After it reaches feature parity, it's going to require a lot of testing effort; by his admission, Thelsing doesn't use macros in his campaigns, and all of the issues that we found with the protobuf change were loading old campaigns and macro related nd they have taken a lot of time to sort out. I believe this renders on the JavaFX thread, so I suspect it will potentially break all the macro functions that are somehow related to the map rendering. From get selected macros to get/set states, on token move, you name it. There could also be obscure interactions with any dialogs like edit token properties. So at this point, it looks to be many, many releases away.

@cwisniew
Copy link
Member

@kwvanderlinde any more thoughts on if we should remove it? I think we have fixed all the other issues for a 1.12.1 build; if you do want to take it out, then it would probably be wise for us to wait for that before releasing 1.12.1. Or do you want to put it behind a preference that defaults to off?

@kwvanderlinde
Copy link
Collaborator Author

I think it's best if we remove it. Keep the new light/darkness/aura overlays, but avoid additive blending for the time being. I can have that put together fairly quickly.

@Phergus
Copy link
Contributor

Phergus commented Sep 24, 2022

Tested. Performance restored.
image

@Phergus Phergus added the tested This issue has been QA tested by someone other than the developer. label Sep 24, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug performance A performance or quality of life improvement tested This issue has been QA tested by someone other than the developer.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants