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

Optimize combining light in ZoneView.getVisibleArea(). #3343

Conversation

kwvanderlinde
Copy link
Collaborator

@kwvanderlinde kwvanderlinde commented Jan 19, 2022

Identify the Bug or Feature request

Addresses #3342.

Description of the Change

Avoid as much contention as possible when combining light areas.

  • Remove the use of a granular lock when populating allLightPathMap.
  • Avoid converting Path2D back to Area until after all lights have been combined.
  • Create allLightAreaMap in the swing worker and return it from there. This avoids any future unintended concurrent
    interactions with allLightAreaMap, and makes it clear that it is only used in ZoneView.getVisibleArea().

Possible Drawbacks

Assuming I've done the concurrency correctly, shouldn't be any drawbacks. If I messed up, all sorts of weird lighting glitches could result.

Documentation Notes

N/A

Release Notes

  • Optimized calculation of visible areas when many lights are present on a map.

This change is Reviewable

@kwvanderlinde kwvanderlinde marked this pull request as draft January 19, 2022 07:56
- Remove the use of a granular lock when populating `allLightPathMap`.
- Avoid converting `Path2D` back to `Area` until after all lights have been combined.
- Create `allLightAreaMap` in the swing worker and return it from there. This avoids any future unintended concurrent
  interactions with `allLightAreaMap`, and makes it clear that it is only used in `ZoneView.getVisibleArea()`.
@kwvanderlinde kwvanderlinde force-pushed the visible-area-performance-improvements branch from 25d9900 to c33deaa Compare January 19, 2022 07:59
@kwvanderlinde
Copy link
Collaborator Author

On my system, this PR reduces contention and improves the multithreaded performance by about >6x in the case described in #3342 (> 40s to < 6.5s for map load). As far as that goes, it could be merged as-is.

But the reason I made this a draft is that I've discovered the multithreading just doesn't scale well for lights. It makes sense when the number of lights is spread across many different lumens values, but in practice this won't be the case as the number of lights grows. That's because it's trivial to attach a light source to a token, but adding new lumens requires defining a new light type. So in cases that "matter", i.e., when there are many light sources, there will be relatively few lumens to split them up by, meaning there will be a lot of contention on allLightPathMap entries. And after some experimentation, that contention can get really bad and grind everything to a halt.

I'll be toying with a different change that just removes multithreading in this case and makes it totally synchronous. By avoiding multithreading overhead and taking advantage of being able to mutate entries in allLightPathMap, this will certainly give benefits over both the current implementation and this PR for the case of many lights with the same lumens value. Depending on how well that experiment goes, I'll open a new PR and close this one off. But early numbers are looking promising...

@kwvanderlinde
Copy link
Collaborator Author

I did some more testing. On my desktop with with a Intel Core i5-9400, this change gives the improvement mentioned in this PR. I've now also tried it on my laptop that has a AMD Ryzen 7 5700U. It does much better already with the existing implementation (~16 seconds) and only saves ~3 seconds. So the benefits may be pretty slim on some hardware, but it should still be a net win.

But it's all seems pretty moot anyways. I've implemented the single-threaded alternative and I'm finding the same case only takes ~1 second on my desktop (~40x improvement) and just shy of 1.5 seconds on my laptop (~12x improvement). So I'm closing this PR in favour of the alternative which is faster, needs less code, and is better for maintenance we don't have to reason about concurrency.

@kwvanderlinde kwvanderlinde deleted the visible-area-performance-improvements branch June 14, 2022 03:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant