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
Performance issues #120
Comments
If you are interested, there are some past conversations in the closed issues where you can have a read and might add some ideas. The tile rendering (drawing on canvas) is currently only possible in the flutter main isolate (flutter/flutter#75755), when I'm not mistaken this is still the bottleneck. You can improve performance by tuning your style. Feel free to do your own experiments and share it with us :) |
We've done a lot of work to address performance issues, but it's still not as good as raster or native maps. Poor performance is most noticeable with tiles having a lot of data (e.g. in LA or London). The theme can make a big difference as noted by @FaFre (thanks!) but you may find that raster tiles are needed to get the performance that you want, depending on your use-case. I've added some examples that you may find helpful here: https://github.com/greensopinion/flutter-vector-map-tiles-examples |
As far as I understand, currently is not possible to optimize it becuse of Flutter limitations? Ok, I will try themes, Indeed, a lot of data causes poor performance. |
@greensopinion I pushed the flutter issue and got a response that However, this plugin is only Android/iOS compatible, do you see any chance this would improve the current performance? |
Yes, there's a good chance that it could be used to offload some CPU-intensive tasks off the UI thread. We are already offloading some work to isolates, but there are many things that can't be offloaded due to use of I imagine that the easiest and most beneficial thing to do would be to render a raster image on an isolate. This could either be integrated directly with the existing I'm a little reluctant to invest in functionality that is using officially unsupported flutter/dart capabilities, such as If we consider moving forward with this idea, we should first evaluate how Impeller affects performance. For example, a comparison running the example library in the profiler with Impeller and without would be really helpful. |
@greensopinion do you think it's possible to disable Impeller and use isolates on Android only? |
At least for now it's possible - but that will likely change once Flutter fully adopts Impeller since they won't want to maintain two separate rendering frameworks for Android indefinitely. |
I don't know how much work is it, but I think better to use isolates on Android, even as temporary solution. Still more than nothing. |
I've pushed an experiment to https://github.com/greensopinion/flutter-vector-map-tiles-raster-experiment |
It works pretty fast, almost the same performance as native Google Maps. Very good result in my opinion. Not tried on iOS though |
Hey I just tried out that experiment on iOS and the performance is really good! |
After more testing. It seems to be better, but still not as good as rester map or native maps like Google Maps. I will test without any style applied to see how does it work, possible only style applied causes better performance |
I've created a branch in this repository for experimentation: flutter-vector-map-tiles/tree/raster-experiment There are a few things needed to take it further:
|
It works really cool. But there is some problem in my case. When I'm panning for a long distance it seems that a huge number of isolates creates for all panned tiles. Seems like tile provider doesn't drop deprecated isolates for tiles which was rapidly panned. For example, I have 100 tiles on the map and I`m trying to pan from 1 tile to 99 tile by one swipe. Tile provider starts to create 99 isolates and tries to process them all but not just skips unnecessary tiles and process only several last tiles. |
The experiment is only intended as a proof-of-concept. There is a lot of work needed to make it ready for real usage. I've been working on #129 to introduce raster images as an alternative to vectors. Raster images have the advantage of improved frame rate (less jank) and they only need to be rendered the first time since they can be stored in the cache for future use. The result is quite good. Of course, raster images aren't as sharp at fractional zoom levels. #129 is now available as version 3.3.0 of this library. |
Thank you, I have already tried this update, it work really faster, but I still have freezes ((. In any case any calculation in main thread entail freezes of the UI. Even if they won't be visible for the human eye, but they will still affect any timer or animation in app. |
Thanks Luke. Is the update to let me know about API changes or does it
specifically relate to performance?
…On Tue, Apr 4, 2023 at 5:15 AM Luka S ***@***.***> wrote:
@greensopinion <https://github.com/greensopinion> Please note
https://pub.dev/packages/flutter_map/versions/4.0.0-dev.1/changelog
—
Reply to this email directly, view it on GitHub
<#120 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AEKDQ7WZYRQ3S72XYZHLMNDW7QGGPANCNFSM6AAAAAAU4Q2O2E>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
@greensopinion Both. Probably not a massive performance improvement, but there is a chance it will help. There are major API changes - but I'm not sure if any of them will affect you. Probably the most major for plugin maintainers is the renaming of |
Thanks @JaffaKetchup - created #136 in preparation for |
Hey @greensopinion, was trying to follow up on your discussion here about using flutter_isolate to offload processing yet still able to call dart.ui functions outside the main isolate. It's not the full solution I understand from your comment here, but part of it. The other part being the complexity of the theme, which you're trying to solve by selectively delaying the rendering if I understood correctly. I'm not sure I got it right, but per nmfisher's (flutter_isolate maintainer) last comment here, the status on this PR being merged into dart's main branch and the comment here, it appears that the functionality that Impeller previously blocked on iOS should now be back again with Dart 3? Does this mean, flutter_isolate + selective delays COULD solve many of our performance issues? What am I missing? |
Hey, @greensopinion - have you considered drawVerticesRaw for rendering? It seems to be orders of magnitude faster than using widgets or canvas. |
Would probably solve all problems with vector maps without going GL? |
Just for context, we're looking into potentially using |
Looks promising! Feel free to prototype something. |
Unfortunately I have neither the time nor skillset to do so. We would however contribute financially with a bounty, if a certain speed level is reached, because then flutter_map would become feasible as an alternative to mapbox for us. |
I might be able to spend some time on this in the near to medium term. So I was wondering, first of all, whether somebody is already working on this or on similar things with |
@j-bbr Right now we are not implementing |
When I say "GPU", I really mean native and what I presume is better GPU access to explain the massive performance differences, apologies for that.
Yes, I do mean flutter-maplibre-gl (layer on top of native/gl_js), HERE (layer on top of native), Google Maps, ... all the vector ones that somehow perform well. Haven't looked at their native implementations though.
Yes, of course :)
I thought you were talking about the maplibre-rs PoC (from the maplibre-rs Github: "maplibre-rs is a portable and performant vector maps renderer. We aim to support web, mobile and desktop applications. This is achieved by the novel WebGPU specification."). No concerns if you're going for the GL ones.
I'm referring to the other vector maps that perform surprisingly well in Flutter. That's the key question I believe most people are trying to answer when choosing between flutter_map + vector plugin and the ones mentioned above.
Got it, thank you.
As per my original clarification above. I'm aware Flutter uses the GPU :)
Alright, then I misunderstood. From the various Flutter links I shared, to me the logic was: (A) we've got tons of drawX calls beyond the 100 or so that 1 post mentioned as a performance drop-off point (B) with vector we can choose to delay rendering layers until others are done (C) I'd personally rather have performance and something looking a bit "weird" with layers like text and polygons if that was a trade-off that was on the table. |
I took a quick look over your changes, they look really good. A few questions:
|
I looked a bit into it. The batches can get large containing sometimes hundreds or over a thousand geometries. I don't think average is a good metric here since it will depend a lot on the tiles (provider, zoom level, where and even styles).
Not a good one, since there are so many variables. I did share my little clips which I tried to keep things the same. That said, panning is the most reproducible but certainly the cheapest.
I have not. I certainly did see visual glitches (e.g. some islands would be fully transparent at certain but not other zoom levels). I'm not ready to blame draw vertices, since this might as well be an issue with my changes. That said, I've been going back and forth on batching vertices and batching paths (which didn't show the same glitches) and both are significant improvements.
I didn't want to ignore you, I just thought your question was racing my reply. To quote myself:
You could consider this "cheating" in terms of vectors. At the end of the day, anything works that leads to less synchronous (re-)renders on the raster thread. Another "cheating" but promising avenue is to simply render fewer bigger tiles at zoom level minus N. |
Thanks for the details! I'm still confused as to how your cling technique
is different than what we are already doing in this library:
https://github.com/greensopinion/flutter-vector-map-tiles/blob/main/lib/src/grid/grid_layer.dart#L144
…On Fri, Feb 9, 2024 at 12:34 AM Sebastian ***@***.***> wrote:
do you have metrics on batching, i.e. the average batch size?
I looked a bit into it. The batches can get large containing sometimes
hundreds or over a thousand geometries. I don't think average is a good
metric here since it will depend a lot on the tiles (provider, zoom level,
where and even styles).
do you have a repeatable method for measuring improvements?
Not a good one, since there are so many variables. I did share my little
clips which I tried to keep things the same. That said, panning is the most
reproducible but certainly the cheapest.
have you looked at whether transparency (e.g. in the line color) works
well with drawVertices?
I have not. I certainly did see visual glitches (e.g. some islands would
be fully transparent at certain but not other zoom levels). I'm not ready
to blame draw vertices, since this might as well be an issue with my
changes. That said, I've been going back and forth on batching vertices and
batching paths (which didn't show the same glitches) and both are
significant improvements.
how is your "clings on to tiles" layer different from using raster mode
<https://github.com/greensopinion/flutter-vector-map-tiles/blob/main/lib/src/vector_tile_layer_mode.dart#L8>
?
I didn't want to ignore you, I just thought your question was racing my
reply. To quote myself:
When I mentioned tile lifecycles, I really just meant we need to hold on
to the tiles and simply not re-render them. I'm also lazy so I didn't
really write my own tiling layer. What you're seeing is FlutterMap's
default tiling layer with a TileProvider that renders vector tiles into
images with an extra Symbol/Text only layer on top. Just like in David's
implementation the cost of the labels is simply mitigated by taking them
off screen while rotating and zooming. When they finally pop in, the
rendering janks terribly but you just don't see it on an otherwise static
screen.
You could consider this "cheating" in terms of vectors. At the end of the
day, anything works that leads to less synchronous (re-)renders on the
raster thread. Another "cheating" but promising avenue is to simply render
fewer bigger tiles at zoom level minus N.
—
Reply to this email directly, view it on GitHub
<#120 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AEKDQ7S72P7HWQIUMJN6353YSXNSFAVCNFSM6AAAAAAU4Q2O2GVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSMZVGUZDCMZQGU>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Maybe you're expecting too much :). I'm rendering into an Image because that let's me control the lifecycle. You're drawing into a CustomPaint widget. RepaintBoundary gives one some limited, best-effort lifecycle control, which you're using to prevent re-renders when panning. However when you're zooming or rotating, you're re-rasterizing on every frame |
Sounds like we are doing the same thing, since with raster mode we are
rendering to an image too.
…On Fri, Feb 9, 2024 at 5:50 AM Sebastian ***@***.***> wrote:
Maybe you're expecting too much :). I'm rendering into an Image because
that let's me control the lifecycle. You're drawing into a CustomPaint
widget. RepaintBoundary gives one some limited control, which you're using
to prevent re-renders when panning. However when you're zooming or
rotating, you're re-rasterizing on every frame
—
Reply to this email directly, view it on GitHub
<#120 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AEKDQ7WLG3BC5OPY65IHCBLYSYSTTAVCNFSM6AAAAAAU4Q2O2GVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSMZVHE3DSNZXGI>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Shame on me, digging through all the layers I actually missed that switch. I took a quick look and unsurprisingly the performance in raster mode is much much better. |
Glad we both had the same good idea!
…On Fri, Feb 9, 2024 at 6:45 AM Sebastian ***@***.***> wrote:
Shame on me, digging through all the layers I actually missed that switch.
I took a quick look and unsurprisingly the performance in raster mode is
much much better.
In that case the only difference is that I'm rendering labels and tiles in
separate passes, i.e. the labels (un)rotate independent from the tiles.
—
Reply to this email directly, view it on GitHub
<#120 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AEKDQ7VWJPJ5SPRAW746UETYSYZAPAVCNFSM6AAAAAAU4Q2O2GVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSMZWGA2TSOBXGQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Agreed. I also never wanted to imply any of it is rocket science. I did it because tapping into the existing FlutterMap tilelayer infra I could do it with rather little effort. Screencast.from.2024-02-09.16-38-24.mp4 |
I have just had a little experiment with a custom Mapbox style, and noticed that setting |
That's cool @JaffaKetchup - can you quantify it? |
I've put a profiling / integration test for vector maps based on this example from the documentation in this repository here. The test simulates map interaction (moving the map, zooming in, flinging the map again, zooming out etc) and records performance related data in a summary (examples attached) and an event trace .json file. The trace file can be viewed with chrome://tracing (see image) As an example I've attached 2 summaries, profiled on a Samsung S20, using the Stadia Maps OSM Bright style once in vector and once in raster mode and moving / zooming over Tokio. |
@j-bbr that's really cool! Having a repeatable way to produce profiling data could help to drive improvements. It's always a challenge to know if a change makes a difference. Do you plan to improve it further? |
Yes, I would like to and I'm open to input for next steps as well. At the moment I am still wondering which metrics are most insightful to compare. For vector mode it's fairly straightforward to see that the frame rasterizer times are above the 16 ms budget for smooth 60 fps but in the raster mode its more difficult to tell from the timelines since the delay happens of the UI-thread. |
@j-bbr It would be awesome if you could make a version without the vector tiles stuff, and it would be much appreciated as a test in FM core! |
Just FYI, interesting debouncing support being added to the core Might be worth checking out for vector also, since the best performance optimization is doing less computations in the first place. |
I am not sure but maybe it can be helpful? https://pub.dev/packages/dart_ui_isolate |
Thanks @mdmm13 that's helpful! I'm curious as to why the default debounce is 0ms. Would you be interested in submitting a PR? A good place to start: https://github.com/greensopinion/flutter-vector-map-tiles/blob/main/lib/src/grid/grid_layer.dart#L144 |
We decided 0 was best as it the feature does impact functionality a fair amount. New tiles aren't loaded at all until the debounce is complete: a long fling will not load any tiles, for examples. |
@Hellomik2002 cool to see more options come up. Do you have any idea how this would be an improvement over We've prototyped something with |
Since dart_ui_isolates came up, I'm going to share my vector tile layer: https://github.com/ignatz/vector_tile_it/tree/main/example . It contains all the optimizations mentioned before and is just generally a bit less layered. That said, it's pretty untested and I'm sure that my wild experiments introduced some regressions. I'm not using it productively myself since I'm still contemplating switching to a rust based rasterizer (at least for the tiles). Enough disclaimer, I played with flutter_ui_isolate to see how much of an impact it has. That said, it's important to note that flutter_ui_isolates are only supported on android, ios and osx. So if you wanna play around with it, it can be easily disabled.
The two main differences are that they have less memory overhead and you can use dart:ui (flutter/flutter#10647). Based on the issue I would have naively expected you to encounter issues but maybe things have improved since the bug was filed in 2017 🤷♀️ |
Sure, but won't it automatically be added as soon as |
Someone know when it will be available? |
@ignatz very cool to see how you were able to integrate the renderer with very little code. |
I'm not quite sure what you have in mind. Don't get me wrong, I'm super appreciative of the work that you've done especially for You can certainly pull in my changes to As for the tile layers, I'm not sure what "I would like to see make it back" or how that would work. My layer takes the hybrid approach: rasterized terrain with crisp vector labels and symbols, has pretty much all I'd expect from a tile layer, and is ~1/3 the code. At the expense of sounding accidentally presumptuous, if you're not happy with the state of Also to be clear, my initial excitement has worn off a bit. I'm not sure that even with all these improvements and changes, flutter-canvas-based vector tiles would meet my personal performance goals. As I've mentioned before, I've toyed with the idea of pushing the rasterization to a mapboxlibre-rs renderer 🤷♀️. But even then it wouldn't be true vector maps but rather faster raster maps with vector labels. I certainly don't get the point of rasterizing everything, why wouldn't I just use raster map tiles? (I guess if you really wanted to change the styling on the client but that sounds rather niche) |
Just FYI, Flutter 3.22 appears to improve tessellation issues drastically. Might help. |
I just quickly ran 3.19 and 3.22 side-by-side. I wasn't sure if Linux was also using the new vulkan-based impeller renderer, looking at the output I'm leaning yes: Maybe worth waiting a few fixes :hide: Also worth highlighting from the article you linked:
|
Thank you for the quick check - looks like a 20-30% performance improvement on average.
The fact that they're stating that in the official announcement means that they're probably working on it :-) |
publish it, let's see it |
I noticed performance when zooming/moving is actually poor in compare to native solutions like Google Maps or Mapbox official api. On low end devices map is almost unusable.
From other side, raster tiles from flutter map plugin are still very fast. Are you aware performance issues and is there anything possible to make it working faster?
The text was updated successfully, but these errors were encountered: