-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Slow performance with lots of empty labels #7973
Comments
@aMoniker thanks for cutting the issue. To ask the obvious, is this a use case we should spend time optimizing for? If we already know there's no text to render, it would make more sense to delay adding the layer. |
@peterqliu Maybe. In our case we were controlling the visibility of labels in one layer by having our tiles server return empty strings for certain features depending on the zoom level. We'll be handling this on the client side due to these performance issues for now, but it may be something we'd like to do again in the future. It's inconvenient for us since we're using multiple clients (iOS & GL-JS) and have to implement that logic twice (and keep both versions in sync). |
It might also be worth filtering out all features with empty strings for that parameter. Could short-circuit a lot of unnecessary work depending on where the bottleneck is |
That's a good idea. We'll try it if we end up going that route again. |
I've been hitting this issue lately. I don't believe it's isolated to empty labels as in my case I'm outputting many thousands of symbols that have values for In an effort to debug this I tried setting the same label for all symbols and allowed overlap and ignore placement:
I hoped this might bypass whatever In my case I need the ability to output many thousands of dense, overlapping symbols as – from what I can see – there's no other way to output a layer with simple shapes as icons (eg. like the circle layer, but triangles or squares). I'd love to find a way to either disable this aspect of the symbol layer or stop it taking so much time. I don't need anything fancy with symbols, just custom icons that otherwise behave like the circle layer. Is there anything I can try? |
@robhawkes nice lead! Can you set up a minimal live example with the problem exaggerated? I'll look into it. |
@mourner I've finally found some time to put together a small test-case that shows the performance problem using a symbol layer with numerous features. https://jsfiddle.net/robhawkes/9uavc0Lp/ If you load up that example and then record a performance profile in Chrome while zooming and panning then you should see something like the following: For some reason the example in JSFiddle is pointing to a different slow-down, however it's in the same parent method as the one described above ( It's worth pointing out that this example uses a GeoJSON source, whereas our real-world issue uses a vector-tile endpoint (that we host on Mapbox). Let me know if I can try anything else to help debug or attempt to by-pass the issue. For comparison, this is the same example but using a circle layer instead – while not expecting them to be identical performance, I would expect symbol layers not to be 25–50x slower for the same number of features: |
@robhawkes thanks for the details! We'll see if there's anything to optimize there, although it will be tough.
Symbol layers are much more difficult to render — we have to transfer the geometry to the main thread, perform global collision detection across different tiles, and update the buffers continuously on every frame. Switching to the new approach significantly improved label density, reliability of collision detection, fade animations of labels, fixed bugs with collisions around tile edges, and enabled collision across multiple sources (see #5150 for a part of this work). It was fine perfomance-wise for the usual use case (e.g. Mapbox basemaps), but it's a trade-off and certainly introduced performance issues for some edge cases. I hope there's still room for improvement though. |
We are hitting this issue pretty hard as well; we have a bunch of logic to remove symbol layers that aren't strictly necessary.
@mourner That makes sense and sounds tough. Is there a way to let mapbox know that we don't care about collision detection? We've tried setting |
Fix coming in #12669 — sorry for getting to this so late! |
mapbox-gl-js version: 0.50.0
browser: Chrome 74.0.3717.0
Steps to Trigger Behavior
Expected Behavior
Works fine. Performant even, because no labels are rendering.
Actual Behavior
Execution thread locks up and browser becomes unresponsive for several seconds. A performance analysis with Chrome devtools reveals that the
findMatches
function incross_tile_symbol_index.js
is taking up most of the execution time:I haven't read through enough of
cross_tile_symbol_index
to find out exactly why, but the comment here makes me guess that empty labels are causing indexes to be clobbered, resulting in lots of unnecessary recalculations.The text was updated successfully, but these errors were encountered: