Leaflet.VectorGrid icon indicating copy to clipboard operation
Leaflet.VectorGrid copied to clipboard

Memory leak when updating data

Open cordlesstuba opened this issue 5 years ago • 6 comments

I load a geojson which contains 40000+ polygons features.

When I update the data, the memory increase a lot until the crash of the browser. Is there a way to clear the cach used by Leaflet.VectorGrid library after updating the data ?

Before update : capture du 2019-01-29 15-16-51

After update: capture du 2019-01-29 15-25-36

Finally: capture du 2019-01-29 15-26-09

function updateData (data) {
                if (tileLayer) {
                    tileLayer.remove();
                    tileLayer = null;
                    tileLayer = undefined;
                }
                
                tileLayer = L.vectorGrid.slicer(data, {
                    rendererFactory: L.canvas.tile,
                    vectorTileLayerStyles: {
                        sliced: function (properties) {
                            return {
                                fillColor: AnalyzeService.hslToHex(properties.color.h, properties.color.s, properties.color.l),
                                fillOpacity: 0.7,
                                fill: true,
                                stroke: false,
                                weight: 0
                            }
                        }
                    },
                    maxZoom: 22,
                    indexMaxZoom: 5,       // max zoom in the initial tile index
                    tolerance: 3, // simplification tolerance (higher means simpler)
                    extent: 4096, // tile extent (both width and height)
                    buffer: 0,   // tile buffer on each side
                    debug: 0,     // logging level (0 to disable, 1 or 2)
                    lineMetrics: false, // whether to enable line metrics tracking for LineString/MultiLineString features
                    promoteId: null,    // name of a feature property to promote to feature.id. Cannot be used with `generateId`
                    generateId: false,  // whether to generate feature ids. Cannot be used with `promoteId`
                    indexMaxPoints: 100000 // max number of points per tile in the index
                }).addTo(map);

                tileLayer.redraw()
        }

cordlesstuba avatar Jan 29 '19 14:01 cordlesstuba

Still have this issue.. If someone has a good idea to resolve it please

cordlesstuba avatar Feb 12 '19 14:02 cordlesstuba

I am facing the same issue.

meersonv avatar Dec 08 '19 11:12 meersonv

Yeah, I'm seeing the same issue. I'm loading 5 GeoJSON layers and within a few minutes of panning/zooming, my memory is shot. When using it on mobile, it crashes after about 5-10 zoom in/outs. This sucks because I'm coding a SaaS platform using this and I'm starting to see that this won't work.

Really hope the author replies to this issue and provides some suggestions or help.

protrackit avatar Jul 20 '20 22:07 protrackit

Alright, I've been digging into this for the past two days and I think I have solved it. At least on my end. I'll describe my set up and use case and what I did to fix it.

I'm using L.mapbox and had to change the onRemove function on the gridLayer. Replace your "tileLayer.remove();" with "tileLayer.removeFrom(map);" and make sure whatever leaflet version you are using has the below onRemove function on the gridLayer.

onRemove: function(t) { this._removeAllTiles(), L.DomUtil.remove(this._container), L.DomEvent.off(this._container), delete this._container, t._removeZoomLimit(this), this._tileZoom = void 0 }

I've sat here for the past hour removing the global layer and re-adding the layer. My memory has not peaked and always drops back down when removing the layer. When you create your layer as a global layer, it creates a memory leak and needs to be cleaned up by using the L.DomUtil and L.DomEvent and then deleting.

This is what's working for me. Hopefully, it will help you as well. Here is my VectorGrid code:

if (window[${group.toLowerCase()}Layer]) { window[${group.toLowerCase()}Layer].off('mouseover'); window[${group.toLowerCase()}Layer].off('mouseout'); window[${group.toLowerCase()}Layer].off('click'); window[${group.toLowerCase()}Layer]._worker.terminate(); window[${group.toLowerCase()}Layer].removeFrom(map); window[${group.toLowerCase()}Layer`] = undefined; }

var layer = turf.featureCollection(JSON.parse(JSON.stringify(pathFeatures)));

window[${group.toLowerCase()}Layer] = L.vectorGrid.slicer(layer, { minZoom: style.visibility[0] || 1, maxZoom: style.visibility[1] || 22, interactive: true, rendererFactory: L.svg.tile, vectorTileLayerStyles: { sliced: function (properties) { return properties.style; } }, getFeatureId: function (feature) { return feature.properties.id; } });`

Let me know if it works!

protrackit avatar Jul 21 '20 23:07 protrackit

Hi, If at all possible, would you please give me your advice in regards my code?

I'm making traffic monitoring system, so I would like to redraw traffic jam layer every 5 minutes. Then I met memory leak trouble above conversation.

I wrote the source code with reference to protrackit's advice, but I couldn't understand how to write onRemove and couldn't remove the layer. Also, createTile is displayed, but it's very slow, so if you have a good way to write it, please give me some advice.

Could you tell me how to fix my code? I'm in big trouble. I would appreciate it if you could help me.

my code(index.php) is following

`

tomo0830-k avatar Apr 30 '21 03:04 tomo0830-k

I had a similar problem and for me the issue was a new worker was started for every layer but never terminated. This solved it for me

layerGroup.eachLayer(function(layer) { layer._worker.terminate() })

jacob-t-radford avatar Apr 12 '23 21:04 jacob-t-radford