ghettovoice / vuelayers

Web map Vue components with the power of OpenLayers
https://vuelayers.github.io/
MIT License
680 stars 227 forks source link

I encountered a performance issue about vl-source-vector #348

Closed zestlee1106 closed 3 years ago

zestlee1106 commented 4 years ago

@ghettovoice Hi. Thank you for creating the vueLayers library. I'm working on showing some markers on the map. I use vl-source-vector for that work. <vl-source-vector :features="positionDataList"></vl-source-vector> And here's the datas that goes into it.

      positionDataList: [
        {
          type: "Feature",
          id: 1,
          geometry: {
            type: "Point",
            coordinates: [127.0198, 37.5897],
          },
        },
        {
          type: "Feature",
          id: 2,
          geometry: {
            type: "Point",
            coordinates: [126.8933, 37.571],
          },
        },
      ],

When I run this code, it runs very low.

If I run it as below, it will be fast.

<vl-geom-multi-point :coordinates="positionDataList"></vl-geom-multi-point>

      positionDataList: [
        [127.0198, 37.5897],
        [126.8933, 37.571],
      ],

Since I am thinking of a hover event, the data should be in object form.

What's the problem?

ghettovoice commented 3 years ago

Hello @a971106a , using features as array is usually faster than multiple vl-feature/vl-geom-*. Can you provide me with demo or example that reproduces this issue? And what you actually mean by low? Rendering of 2 features usually not significantly differ between two ways.

If you layer have a huge number of features, then you should probably switch to the vector tiles or something similar.

vickyrare commented 3 years ago

Hello ghettovoice,

I am having trouble loading around 10000 features as an array. It used to work with vuetify 1.5.18 and vue 2.6.6 but after upgrading to vuetify 2.6.9 and vue 2.6.12 it takes longer and most of the time just fails with Chrome throwing unresponsive script error.

Any help would be appreciated.

ghettovoice commented 3 years ago

This is quite a big array to show, especially if it become reactive in Vue. There are no silver bullet to resolve this, just a several recommendations:

  1. Maybe you don't need all 10k features at the single moment. So you can use bbox loading strategy (show only what in the map view), vl-source-vector supports it. Use clustering on low zoom levels. Clustering maybe done on the client (easy to integrate, but have some load on the client) or with backend.

  2. load vector features with VectorTiles. vl-layer-vector-tile/vl-source-vector-tile support this. Need a map server.

  3. If this features don't have any interaction on the map, they can be loaded through WMS as image tiles. Need a map server.

  4. If you still need to load all 10k features and don't have any opportunity to use vector tiles. You can try to work with features through the native OpenLayers api, avoiding all VueLayers/Vue reactivity overhead. Sometimes this is works too, sometimes now, because you obviously loose reactivity, but you still can subscribe to openlayers events. So you only use vl-layer-vector/vl-source-vector components just to configure them, but load/add/remove features through native OpenLayers API.

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

vickyrare commented 3 years ago

Just a small correction. I was trying to load around 1000 features with clustering. It used to work with vuetify 1.5.18 and vue 2.6.6 but after upgrading to vuetify 2.6.9 and vue 2.6.12 it takes longer.

<vl-layer-vector :z-index="3000">
<vl-source-cluster :distance="50">
<vl-source-vector :features="features">
</vl-source-vector>
<vl-style-func :factory="clusterStyleFunc" />
</vl-source-cluster>
</vl-layer-vector>

Any help would be appreciated.

ghettovoice commented 3 years ago

@vickyrare interesting observation. Do you sure that vuelayers version never changed during this upgrade? And do you have some demo or example of your map component with the data that you load?

vickyrare commented 3 years ago

@ghettovoice I have created a new private repository which contains a small example which demonstrate the slowness issue between vuetify 1.5.18 and vuetify 2.6.10.

I have given you access to the private repository.

https://github.com/vickyrare/vuelayers_issue

This repository has two commits.

Commit 1 uses Vuetify 2.6.10 (commit id: 6745764848f618656368c50bf2c5a4778a0325d3) Commit 2 uses Vuetify 1.5.18 (commit id: 9c95761ebca6dcf99e5eff1d98693aab1f96bdd2 )

General zoom in and out works ok. The problem shows up when we search for something or check / uncheck "Show Offline" when zoomed in around level 12 onwards.

How to reproduce the issue.

  1. Zoom in to maximum level and (type in 30123 or check / uncheck "Show Offline")
  2. The problem does not show up if we zoomed out at level 10 (default)

How to run the app

  1. Go to the vuelayers folder
  2. Run yarn
  3. Run yarn serve
ghettovoice commented 3 years ago

@vickyrare great! I will check it soon 👍

ghettovoice commented 3 years ago

@vickyrare I have just published new vuelayers version, v0.11.31 that should resolve this issue. You can check upd branch in your repo.

vickyrare commented 3 years ago

@ghettovoice That seems to fix the issue. Thank you for your help.

Now came across another issue which is related to the previous issue. In this case, I am showing around 10000 features with clustering. The problem is this case is that the zoom in / out from the map is sluggish.

When you zoom in / out, the map freezes for few seconds. In that period the user cannot zoom in / out or pan.

I have updated the previous repo (branch upd) and added more features to reproduce the issue. Please have a look at your convenience.

Thanks in advance.

ghettovoice commented 3 years ago

@vickyrare I currently can't do anything with this. vl-source-cluster should react on each ol/source/Cluster change (actually on each zoom, center change and so on) to be synchronized with it, each time it need to serialize current clustered features and fire them with Vue update:feature event. All these things triggers a lot of reactive changes that is sore spot in Vue, it's magic reactivity always comes with additional CPU load.

In your case with >= 5k clustered features, the only way is to avoid Vue reactivity on a hot parts. You can use vuelayers component to configure map, view, layers, tile sources as always. But inject and use cluster vector source natively through OpenLayers API. Take a look at the example in your demo repo in the native-cluster branch.

About updated demo addition: I didn't remove clustered*Features computed properties that are reactive, just return from them with Object.freeze. This should be usually enough, but to fully avoid Vue in this use case, you also need non reactive props for each source and synchronize them manually through watcher

vickyrare commented 3 years ago

@ghettovoice I have gone through the demo code inside the native-cluster branch and manage to fix my issue. Many thanks !!