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

I encountered a performance issue about vuelayers... #196

Closed
jerry1108 opened this issue Jul 11, 2019 · 12 comments
Closed

I encountered a performance issue about vuelayers... #196

jerry1108 opened this issue Jul 11, 2019 · 12 comments

Comments

@jerry1108
Copy link

dear @ghettovoice :
I encountered a performance issue about vuelayers.
At present, there are 600 points and 33 line-strings on my map.
I let the lines appear when zoom >= 15 && zoom <= 19 and those points appear when zoom >= 20.
While I zoom in the map, those lines disappear and the points appear after about 2~5 seconds and thus the action causes a little lag.
While I zoom out the map, those points disappear and the lines appear after about 2 seconds and thus the action also causes a little lag. (but sometimes the lines can't appear and the points can't disappear...)
These two conditions both cause the CPU rate to raise vary high. Especially in first scenario. So my customer always complain about the bad user experience.
Could you do me a favor to check if there is something wrong or wierd in my codes?

<vl-map :load-tiles-while-animating="true" :load-tiles-while-interacting="true" :controls="false" class="map-canvas" ref="map" v-on:click="onMouseClick"  v-on:pointermove="onPointerMove" v-on:mounted="onMapMounted" @@movestart="onMovestart" @@moveend="onMoveend" data-projection="EPSG:4326" :style="{cursor: mapCursor}">
	<vl-view ref="view" :zoom.sync="zoom" :center.sync="center" :enable-rotation="false" :min-zoom="minZoom" :max-zoom="maxZoom" projection="EPSG:3857"></vl-view>

	@*points*@
	<div v-for="(point, index) in overlays.AllPoints" :key="'markers_'+ point.Id">  
		<vl-feature :id="'point_'+ point.Id" :properties="point" v-if="zoom >= 20">
			<vl-geom-point :coordinates="[point.Lon, point.Lat]"></vl-geom-point>
			<vl-style-box>
				<vl-style-circle :radius="16">
					<vl-style-fill :color="point.Color"></vl-style-fill>
				</vl-style-circle>
			</vl-style-box>
			@if (!_AccountLoginData.IsLoging)
			{
				<vl-overlay :position="[selectedPointFeatures.Longitude, selectedPointFeatures.Latitude]" :offset="[0, -10]" :positioning="'bottom-center'" :key="selectedPointFeatures.PointID" :id="selectedPointFeatures.PointID" v-if="zoom >= 20">
					<div class="map-Info-area dec-tabs" style="position:relative;z-index:99;"> XXX </div>
				</vl-overlay>
			}
			else
			{
				<vl-overlay :position="[selectedPointFeatures.Longitude, selectedPointFeatures.Latitude]" :offset="[0, -10]" :positioning="'bottom-center'" :key="selectedPointFeatures.PointID" :id="selectedPointFeatures.PointID" v-if="zoom >= 20">
					<div class="map-Info-area dec-tabs" style="position:relative;z-index:99;"> XXX </div>                    
				</vl-overlay>                  
			}
		</vl-feature>
	</div>


	<vl-layer-tile id="osm">
		<vl-source-osm></vl-source-osm>		           
	</vl-layer-tile>

	@*line-strings*@
	<vl-layer-vector v-for="(feature, index) in overlays.AllLines.features" :key="'line_'+ feature.properties.Id">                        
		<vl-source-vector :id="'vl_'+ index">                                
			<vl-feature :id="'line_'+ feature.properties.Id" :properties="feature.properties" v-if="checkLineShow()">
				<vl-geom-line-string :coordinates="feature.geometry.coordinates"></vl-geom-line-string>
					<vl-style-box>
						<vl-style-stroke :color="setLineColor(feature.properties)" :width="3"></vl-style-stroke>
					</vl-style-box>
			</vl-feature>
			<vl-overlay :position="feature.properties.CenterPosition" v-if="checkCountShow(feature.properties)"></vl-overlay>
			<vl-overlay :position="selectedLineFeatures.Position" :offset="[0, -9]" :positioning="'bottom-center'" :key="selectedLineFeatures.LineId" :id="selectedLineFeatures.LineId" v-if="checkLineShow()">
				<div class="map-Info-area dec-tabs" style="position:relative;z-index:99;"> XXX <div>
			</vl-overlay>                             
		</vl-source-vector>                                          
	</vl-layer-vector>                    


</vl-map>

However if I let the point amount lower to about 250, the lag situation has gone.
I discuss with my colleague who had implement the original openlayers map and he said he added over 5000 points (feature layer) on the map, it worked well while dragging or zooming-in or zooming-out the map.
So I wonder if I write out the bad codes or something else??? I don't understand. :((

@ghettovoice ghettovoice self-assigned this Jul 11, 2019
@ghettovoice
Copy link
Owner

Hi @jerry1108 ,
the main reason for lags is vl-feature component for each feature. Vue doesnt support something like virtual components, so for each vl-feature it creates html element in the dom. When you zoom map through line <-> point break points Vue actually recreates 600 dom elements that can be efficient in any case.

My suggestion is do not use vl-feature for this use cases, actually this components is only convenient way to render single marker or several static markers. In your use case you should pass features to vl-source-vector through features property as array of GeoJSON encoded objects. Then this layers will have performance comparable to native openlayers. Also you can use visible property of the vl-layer-* components to switch layer visibility according to zoom or some other conditions, this will be more efficient than use of v-if that re-creates layers.

Here is simple example https://jsfiddle.net/ghettovoice/qvxr1hLn/

@jerry1108
Copy link
Author

jerry1108 commented Jul 12, 2019

Hi @ghettovoice :
Thank you very much for your help and explanation.
It seems all points or lines are bound to one vl-source-vector.
The original scenario is that users would click at any point or any line and then popup window (vl-overlay) appears to show its information respectively. Then I get the properties from each of vl-feature and then pass them to vl-overlay.
So how do I recognize which point (or line) in the vl-source-vector?

@ghettovoice
Copy link
Owner

I have made update to this example https://jsfiddle.net/ghettovoice/qvxr1hLn/
vl-interaction-select is the key component for selected features detection.

@jerry1108
Copy link
Author

jerry1108 commented Jul 13, 2019

I have made update to this example https://jsfiddle.net/ghettovoice/qvxr1hLn/
vl-interaction-select is the key component for selected features detection.

@ghettovoice
Thank you for your demo codes.
However, each point or line has its own properties, such as color and other information.
Their color will change depend on the status or some statistics information.
So How can I let each point or line get their color from geojson properties and inject them into vl-source-vector?
I tried and survey several hours and failed.

@ghettovoice
Copy link
Owner

The most easy and flex solution for dynamic styles is the so called style function.
Take a look at the updated example https://jsfiddle.net/ghettovoice/qvxr1hLn/.

@jerry1108
Copy link
Author

jerry1108 commented Jul 13, 2019

@ghettovoice :
Thank you for ur great help.

@jerry1108
Copy link
Author

@ghettovoice :
I have another question is that I get the real-time api (the status of those points) and if the status of certain point is 1 and I will set its color to red and if the status is 0 and I will set its color to green.
I try to use vm.$set to change the color property in the geojson of the points data but that point color didn't change. Is there any method to achieve the goal? Thank you.

@jerry1108
Copy link
Author

@ghettovoice :
As the above question, I found an example in the similar issue: (dynamically update the color)#68
https://jsfiddle.net/ghettovoice/bjtr79o8/

I move the pointsStyleFunc to comuted block, and all points disappear... Why?

@ghettovoice
Copy link
Owner

I move the pointsStyleFunc to comuted block, and all points disappear... Why?

Maybe you make computed property a bit incorrect, it should return the function that return style function.
i.e.

...
computed: {
  pointsStyleFunc () {
    return () => feature => {
      // style function body
    }
  },
},
...

But with the latest version v0.11.5-beta.3 you don't actually need this, because here was fixed several issues related to feature updates.
https://jsfiddle.net/ghettovoice/qvxr1hLn/

@jerry1108
Copy link
Author

jerry1108 commented Jul 15, 2019

@ghettovoice :
I used the latest version v0.11.5-beta.3 in my web and suddenly the cpu and memory usage raised very high and the browser crashed. And I changed back to 0.11.4 and it worked well but their color couldn't change.
I gusess the 600 points initially change their color in a few seconds to cause this situation.
I made the similar situation by rewirting your demo codes to:
setInterval(() => { this.lines.forEach(line => { line.properties.color = colors[_.random(0, colors.length - 1)] }) }, 100)
The cpu and memory usage also raised high and the browser didn’t crush but lag severely~~
What can I do to resolve this situation?
Why the old codes (using vl-feature) can let these points change color smoothly depending on real-time status API? (use websocket to subscribe point status from some platform)

@ghettovoice
Copy link
Owner

ghettovoice commented Jul 15, 2019

Why the old codes (using vl-feature) can let these points change color smoothly depending on real-time status API? (use websocket to subscribe point status from some platform)

Because in the v0.11.4 only the array changes are tracked, not internal feature properties. But vl-feature is another component, that watches for all its properties, so there properties changes are tracked.

If you have a lot of frequent changes for features, the only really effective way to work them is avoid using Vue at all, i.e. exclude using of vl-feature and vl-source-vector so you don't have reactive array of features. A lot of frequent updates of the reactive array will always beats on the CPU, I found that Vue not so good in such use case. And usually use only basic VueLayers components to configure the map, but work with huge very dynamic sources with native OpenLayers API.
Take a look for updated example https://jsfiddle.net/ghettovoice/k6071csq/.

@stale
Copy link

stale bot commented Oct 6, 2019

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants