Thursday 2 September 2021

Browser(Chrome and Firefox) running out of Memory when using CesiumJS lookAt method multiple times

Why do I run out of memory after calling CesiumJS' lookAt method multiple times? For a project, I want to look at many different points one after another and for that call the lookAt function looping over these points. After a few calls, the responses are slower and slower and the browsers memory usage is increasing constantly, up to the point that I get an out of memory error. I ran the code locally in both Firefox and Chrome. Both are experiencing this error after between 30 and 300 runs depending on the camera distance, as it seems, greater distance requires more tiles to be loaded and thus the memory error happening faster. But also in the sandcaslte: https://sandcastle.cesium.com/, I was experiencing the issue that my Browsers memory is increasing up to the point that the browser crashes.

My computer has 32GB memory. After about around 30 times calling lookAt Firefox consumes 20GB of memory before I can see the our of memory error on the developer console. Chrome only consumes 8 GB before running into out of memory, but seems to procress the calls faster.

Does anyone have an idea, what could be the matter? I did try to destory the viewer after each look at, but that did not help at all. Thanks a lot in advance your your help!!!

You can paste the following code into sandcastle as is. Only more coordinates are required, as I removed most of them for better readability.

/*I have added around 350 points here, but to improve readbility, I removed most of them 
  const points = [
  [49.311814789194564, 6.670985819810598],
  [48.311814789194564, 6.670985819810598],
[50.311814789194564, 6.670985819810598]
];*/

//random generation instead for testing purposes
const points = Array(350).fill().map((_, index, a) => ([42 + 20/a.length * index, 20/a.length * index]));


function awaitTileLoadingComplete(viewer){
  return new Promise((resolve) => {
    const listener = () => {
      if(viewer.scene.globe.tilesLoaded) {
        viewer.scene.globe.tileLoadProgressEvent.removeEventListener(listener);
        resolve();
      }
    };
    viewer.scene.globe.tileLoadProgressEvent.addEventListener(listener);
  });
}

async function getTerrainHeight(long, lat, viewer){
  const pointOfInterest = Cesium.Cartographic.fromDegrees(
    long, lat, 5000, new Cesium.Cartographic()
  );  
  return (await Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, [pointOfInterest]))[0].height;
}

async function lookAt(viewer, lat, lon, heading, pitch, range) {
  heading = Cesium.Math.toRadians(50.0);
  pitch = Cesium.Math.toRadians(pitch);
  viewer.camera.lookAt(
    Cesium.Cartesian3.fromDegrees(lon, lat, await getTerrainHeight(lon, lat, viewer) + 100),
    new Cesium.HeadingPitchRange(heading, pitch, range)
  );
}

async function lookAtPointAndWait(viewer, point) {
  await lookAt(viewer, point[0], point[1], 90, -3, 5000);
  await awaitTileLoadingComplete(viewer);
  // Wait a second for everything to actually be rendered:
  await new Promise(resolve => setTimeout(resolve, 1000));
}

async function main() {
  const viewer = new Cesium.Viewer("cesiumContainer", {
    terrainProvider: Cesium.createWorldTerrain(),
  });     
  viewer.scene.debugShowFramesPerSecond = true;
  viewer.scene.fog.enabled = false;
  viewer.scene.primitives.add(Cesium.createOsmBuildings());
  
  await points.reduce(
    (promise, point) => promise.then(() => lookAtPointAndWait(viewer, point)),
    Promise.resolve()
  );
}

main();


from Browser(Chrome and Firefox) running out of Memory when using CesiumJS lookAt method multiple times

No comments:

Post a Comment