多次调用CesiumJS的lookAt方法导致Chrome、Firefox浏览器内存溢出
问题根因
- Cesium默认未限制瓦片缓存上限:地形、影像、OSM建筑瓦片在跳转不同点位时会持续加载到内存,默认策略是尽可能缓存所有访问过的瓦片,不会主动释放长期未使用的瓦片资源。
- 跨平台WebGL资源回收效率差异:Windows端NVIDIA显卡驱动对WebGL纹理、顶点缓冲区等资源的垃圾回收阈值更高,未使用的GPU资源不会被及时释放,所以内存上涨速度远快于Linux端Intel核显环境。
- 销毁操作不彻底:如果直接销毁viewer实例但未手动清空关联的缓存资源、置空引用,浏览器GC不会立刻回收对应的WebGL资源,无法解决内存上涨问题。
- 高频高程查询产生额外临时对象:每次调用
lookAt都执行sampleTerrainMostDetailed请求高程,会产生大量异步请求回调、临时坐标对象,进一步加剧内存占用。
修复方案
- 限制瓦片缓存容量
初始化viewer后主动设置瓦片缓存大小,强制Cesium只保留最近使用的指定数量瓦片:
// 地形瓦片缓存数量,可根据需求调整,数值越小内存占用越低 viewer.scene.globe.tileCacheSize = 20; // 调整屏幕空间误差阈值,避免加载过细的冗余瓦片 viewer.scene.globe.maximumScreenSpaceError = 2; // 若使用OSM建筑图层,也同步限制其缓存大小 const osmBuildings = Cesium.createOsmBuildings({ maximumTileCacheSize: 15 }); viewer.scene.primitives.add(osmBuildings);
如果使用自定义影像Provider,也可以对应设置其tileCacheSize参数。
- 主动触发旧瓦片销毁
每次跳转完一个点位、瓦片加载完成后,主动标记旧瓦片为可销毁:
// 在lookAtPointAndWait的awaitTileLoadingComplete之后调用 viewer.scene.globe.invalidateAllTiles();
- 优化高程查询逻辑
提前批量查询所有点位的高程数据并缓存,不要每次跳转时实时请求:
// 初始化时一次性查询所有点位高程 async function prefetchAllHeights(points, viewer) { const cartographics = points.map(p => Cesium.Cartographic.fromDegrees(p[1], p[0], 5000)); const results = await Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, cartographics); return results.map(r => r.height); }
- 正确的viewer销毁逻辑(如果需要多实例场景)
// 销毁前先清空场景资源 viewer.scene.primitives.removeAll(); viewer.destroy(); viewer = null; // 等待一帧再新建viewer,给GC留出回收时间 await new Promise(resolve => requestAnimationFrame(resolve));
- 额外优化项
开启雾效减少远处瓦片加载,限制相机远裁剪面:
viewer.scene.fog.enabled = true; viewer.camera.far = 50000; // 根据你的可视范围调整
内容的提问来源于stack exchange,提问作者lukro
相关产品推荐
相关产品推荐

