angular-cesium icon indicating copy to clipboard operation
angular-cesium copied to clipboard

Reusing map viewer.

Open h11a opened this issue 5 years ago • 5 comments
trafficstars

Hi,

I have a problem with memory usage, I need to only show a cesium map on one page which the user can navigate to and from. As The cesium viewer keeps getting created in the component the chrome tabs memory usage keeps going up.

I made an issue on the cesium js github and they told me to avoid recreating the cesium viewer and instead store it and reuse it. When we do need to destroy it we need to actually dispose of all the resources correctly so memory is released. The original issue can be seen here.

As we actually use angular cesium I am a little unsure how to store this. Could anyone provide some assistance?

Thanks

h11a avatar May 15 '20 13:05 h11a

Hi, You can do this in the parent component of your <ac-map>:

   ngOnDestroy(): void {
     const viewer = this.mapsManagerService.getMap().getCesiumViewer();
     viewer.destroy();
  }

more about MapsManagerService here.

I didn't experience this kind of memory issue by myself, let me know if it worked. I am considering adding viewer.destory() to ac-map.component ngOnDestory().

eitanfr avatar May 15 '20 15:05 eitanfr

Hi,

I have tried adding the viewer destroy and it always produces the following error

core.js:6014 ERROR Error: Uncaught (in promise): TypeError: e[i].destroy is not a function
TypeError: e[i].destroy is not a function
    at PrimitiveCollection.removeAll (Cesium.js:23)
    at PrimitiveCollection.destroy (Cesium.js:23)
    at PrimitiveCollection.removeAll (Cesium.js:23)
    at PrimitiveCollection.destroy (Cesium.js:23)
    at Scene.destroy (Cesium.js:23)
    at CesiumWidget.destroy (Cesium.js:23)
    at Viewer.destroy (Cesium.js:23)
    at MapComponent.ngOnDestroy (map.component.ts:165)
    at callProviderLifecycles (core.js:32334)
    at callElementProvidersLifecycles (core.js:32293)
    at resolvePromise (zone-evergreen.js:797)
    at resolvePromise (zone-evergreen.js:754)
    at zone-evergreen.js:858
    at ZoneDelegate.invokeTask (zone-evergreen.js:391)
    at Object.onInvokeTask (core.js:39680)
    at ZoneDelegate.invokeTask (zone-evergreen.js:390)
    at Zone.runTask (zone-evergreen.js:168)
    at drainMicroTaskQueue (zone-evergreen.js:559)
    at ZoneTask.invokeTask [as invoke] (zone-evergreen.js:469)
    at invokeTask (zone-evergreen.js:1603)

This is coming from the following lines

    PrimitiveCollection.prototype.removeAll = function() {
        for (var e = this._primitives, t = e.length, i = 0; i < t; ++i)
            delete e[i]._external._composites[this._guid],
            this.destroyPrimitives && e[i].destroy();
        this._primitives = []
    }

This exceptions is likely due to adding ac- models. I do this using the following code.

    <ac-map [sceneMode]="">
        <ac-layer acFor="let track of placeHolderObj$" [context]="placeHolderService" [debug]="true">
            <ac-model-desc props="{
                scale: track.blenderObject.positionSettings.scale.toString(),
                position: track.blenderObject.positionSettings.degreePosition,
                orientation: track.blenderObject.positionSettings.orientation,
                uri: track.blenderObject.gltfBlob.toString(),
                color: track.getAsCesiumColour(track.color),
                show: track.visible,
                shadows: Cesium.ShadowMode.CAST_ONLY
                }">
            </ac-model-desc>
        </ac-layer>
        <ac-layer acFor="let track of placeHolder$" [context]="placeHolderService" [debug]="true">
            <ac-array-desc acFor="let blenderObject of track.blenderObjects" [show]="true"
                           [idGetter]="blenderObjectIndex">
                <ac-model-desc props="{
                scale: blenderObject.positionSettings.scale.toString(),
                position: blenderObject.positionSettings.degreePosition,
                orientation: blenderObject.positionSettings.orientation,
                uri: blenderObject.gltfBlob.toString(),
                color: track.getAsCesiumColour(track.color),
                show: track.visible,
                shadows: Cesium.ShadowMode.DISABLED
                }">
                </ac-model-desc>
            </ac-array-desc>
        </ac-layer>
    </ac-map>

I also tried to clear them up using the code below before destroying the viewer but it didnt help.

        for (let i = 0; i < this.placheHolderShapes.length; i++) {
            this.placeHolderObj$.next({
                id: i.toString(),
                entity: new AcEntity(this.placheHolderShapes[i]),
                actionType: ActionType.DELETE,
            });
        }

In the original issue somebody also set I should be unsubscribing from my observable s that the ac-layer uses [ Here]. Is this something that also needs doing and if so how do you do it?

h11a avatar May 22 '20 10:05 h11a

Hi, I think this is an issue that is already resolved. do you use the latest version of angular-ceisum?

eitanfr avatar May 23 '20 14:05 eitanfr

Ah my bad that seems to have fixed it. I have made sure to clear any event listeners, imagery layers and objects added to cesium in the ngOnDestroy()... Great news it no longer eats all the ram until it crashes.

However the tab still shows to be using 5gb memory on my task manager (although doesnt go higher than this)... Is there a way I can store the viewer in a service and load it back into cesium? Or get it to actually release all the resources and not just some of them.

I have read the high usage seems to be a problem with chrome in this issue here.

Thanks for the help

h11a avatar May 26 '20 11:05 h11a

Hi @eitanfr have you managed to get a change to look at this?

h11a avatar Jun 10 '20 11:06 h11a