OpenLayer not releasing memory even after disposing the map

139 Views Asked by At

I have created a map using openlayer, where i created a Vector Layer from geoJson data. Now even when my component unmounts, this component do not release associated memory, instead it keep adding memory wen remount.

  constructor(props) {
        super(props);
        this.state = {
            center: [0, 0],
            zoom: 0,
            map: null
        };
        this.mapIsSet = false;
        this.initialExtentSet = false;
        this.rotation = 0
        this.image = new CircleStyle({
            radius: 5,
            fill: new Fill({color: '#00e600'}),
        });
    }
componentDidMount() {

        // Create vector sources
        this.feature1Source = new VectorSource({ wrapX: false });
        this.feature2Source = new VectorSource({ wrapX: false });
        this.feature3Source = new VectorSource({ wrapX: false });
        this.pointSource = new VectorSource({ wrapX: false });

        this.Feature1 = new Feature(
            {
                geometry:new Point([0, 0]),
                style: this.getIconStyle('feature1')
            }
        )
        this.Feature3 = new Feature(
            {
                geometry:new Point([0, 0]),
                style: this.getIconStyle('feature3')
            }
        )
        this.feature2LineString = new LineString([])
        this.Feature2 = new Feature({
            geometry: this.feature2LineString,
            style: this.feature2Style
        });

        this.feature1Source.addFeature(this.Feature1)
        this.feature3Source.addFeature(this.Feature3)
        this.feature2Source.addFeatures([this.Feature2, this.Feature1])

        // Create layers 
        this.feature1Layer = new VectorLayer({
            source: this.feature1Source,
        });
        this.feature2Layer = new VectorLayer({
            source: this.feature2Source,
            style: this.toolStyle,
        });
        this.feature3Layer = new VectorLayer({
            source: this.feature3Source,
        });
        this.pointLayer = new VectorLayer({
            source: this.pointSource,
            style: new Style({
                image: new RegularShape({
                    fill: new Fill({color: '#00e600'}),
                    points: 4,
                    radius: 7,
                    angle: Math.PI / 4,
                }),
            }),
        });

        if(!this.state.map) {
            const map = new Map({
                target: 'map-container',
                interactions: defaults({mouseWheelZoom: false}),
                controls: [],
                view: new View({
                    projection: "EPSG:6675",
                    center: this.state.center,
                    zoom: this.state.zoom,
                }),
            });
            // Add layers to the map
            map.addLayer(this.feature3Layer);
            map.addLayer(this.feature1Layer);
            map.addLayer(this.feature2Layer);
            map.addLayer(this.pointLayer);
            this.setState({map: map})
        }

I have this setup to initiate my react component for loading a map from geojson file.

In componentDidUpdate i call an update function, like this

updat(){
    if (this.props.geoJsonMap !== null && !this.mapIsSet) {
          this.vectorSource = new VectorSource({
              features: new GeoJSON().readFeatures(this.props.geoJsonMap),
          });
          this.vectorLayer = new VectorLayer({
              source: this.vectorSource,
              style: this.styleFunction,
          });
          this.state.map?.addLayer(this.vectorLayer)
          this.state.map?.getView().fit(this.vectorSource.getExtent());
          this.mapIsSet = true
      }
// My rest of update codes
}

So i create a vector layer only once in my component lifecycle. And when component unmounts i do following

componentWillUnmount() {

        // Clear vector sources
        this.stop();
        this.machineSource.clear();
        this.toolSource.clear();
        this.bucketSource.clear();
        this.pointSource.clear();
        this.vectorSource.clear()
        this.toolLineString.dispose();
        this.toolLineString = null;

        if(this.state.map){
            this.state.map.removeLayer(this.bucketLayer);
            this.state.map.removeLayer(this.machineLayer);
            this.state.map.removeLayer(this.toolLayer);
            this.state.map.removeLayer(this.pointLayer);
            this.state.map.removeLayer(this.vectorLayer);
            this.state.map.dispose();
        }

        // Nullify the sources and layers
        this.vectorSource = null;
        this.machineSource = null;
        this.toolSource = null;
        this.bucketSource = null;
        this.pointSource = null;
        this.bucketLayer = null;
        this.machineLayer = null;
        this.toolLayer = null;
        this.pointLayer = null;
        this.vectorLayer = null;

    }

I explicitely remove all layers, sources, and also make them null.

But still i see, the memory consumed by the map is not released, even if i am not in this component, it keeps the memory. Specially the memory that it consumed for creating vector layer using geojson data. Now, my geojson data is huge, for each time it loads, it takes 400-500MB memory. Now everytime my component unmount and mount, this memory adds up, eventually hang my system. any idea whats wrong?

1

There are 1 best solutions below

0
Criminal_Affair_At_SO On

You are not removing vectorLayer each time your component updates. Your component will grow at each update.

Also you are not removing the features layers and the features when unmounting.

Try going in the Memory tab of Chrome DevTools and make a heap snapshot after a few remounts to see what are the objects that keep piling up.