CesiumJS активно использует WebGL, асинхронную загрузку тайлов, кэширование геоданных и сложную систему сущностей сцены. Это создаёт многослойную модель памяти, в которой утечки могут возникать не только в JavaScript-объектах, но и в GPU-контексте, кэшах текстур и буферах рендеринга.
Ключевая особенность заключается в том, что освобождение памяти в CesiumJS не всегда происходит автоматически при удалении объектов из сцены. Некоторые структуры требуют явного вызова методов очистки, иначе ссылки остаются в:
Утечка может проявляться как постепенный рост RAM и VRAM при неизменной сцене или при повторных переходах между состояниями приложения.
Добавление сущностей через viewer.entities.add() без
последующего удаления приводит к накоплению ссылок в коллекции.
Особенно критичны случаи:
remove или removeAllПроблема усугубляется, если сущности содержат MaterialProperty с анимацией.
Одним из наиболее частых источников утечек является обработчик событий:
new Cesium.ScreenSpaceEventHandler(scene.canvas)setInputAction(...)Если обработчик не уничтожается через destroy(), он
продолжает удерживать ссылки на scene и viewer.
Особенно опасны сценарии SPA, где компоненты создаются и уничтожаются многократно.
3D Tiles используют агрессивное кэширование:
Даже после удаления tileset из сцены:
viewer.scene.primitives.remove(tileset);
без вызова:
tileset.destroy();
часть ресурсов может остаться в памяти.
Дополнительно важно учитывать tileset.maximumMemoryUsage
и кэш плиток в TileCache.
Imagery layers часто создаются и заменяются динамически:
Удаление слоя без явного освобождения:
viewer.imageryLayers.remove(layer);
не гарантирует мгновенное освобождение WebGL-текстур. При интенсивной смене слоёв происходит накопление GPU памяти.
Low-level primitives:
могут удерживать буферы GPU даже после удаления из коллекции, если:
destroy()Утечки на уровне JavaScript часто связаны не с Cesium напрямую:
setInterval без очисткиrequestAnimationFrame в циклических обновленияхОсобенно опасны замыкания, содержащие ссылки на viewer,
scene или entity.
Основной инструмент анализа:
Ключевые признаки утечки:
Entity,
Cesium3DTileset, Texture)Позволяет выявить:
Особенно полезно для выявления утечек в
requestRenderMode выключенном режиме.
Встроенный инструмент:
Активируется через:
viewer.scene.debugShowFramesPerSecond = true;
Дополнительно можно отслеживать:
viewer.scene.globe.tilesLoadedРазделение приложения на независимые сценарии:
Позволяет определить подсистему, вызывающую рост памяти.
Каждый Cesium-объект должен проверяться на наличие метода:
destroy()isDestroyed()Пример типовой ошибки:
const handler = new Cesium.ScreenSpaceEventHandler(canvas);
// отсутствие handler.destroy()
Часто утечки возникают из-за:
viewer.camera.changed.addEventListenerscene.preRender.addEventListenerclock.onTickБез явного удаления через removeEventListener.
При разрушении приложения:
viewer.destroy();
Это освобождает:
Отсутствие вызова приводит к накоплению WebGL контекстов при повторной инициализации.
viewer.entities.removeAll();
viewer.scene.primitives.removeAll();
viewer.imageryLayers.removeAll();
При этом важно учитывать, что removeAll не всегда вызывает destroy у вложенных объектов.
Корректный жизненный цикл:
viewer.scene.primitives.remove(tileset);
tileset.destroy();
Также требуется обнуление ссылок:
tileset = null;
handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
handler.destroy();
handler = null;
CesiumJS использует WebGL, поэтому утечки могут быть скрыты в виде:
Особенности:
Дополнительный индикатор — рост GPU Memory в Chrome Task
Manager.
Создание нового viewer без уничтожения старого:
Хранение объектов в:
Неправильно реализованные callback-и:
Зафиксировать базовый heap snapshot
Выполнить сценарий взаимодействия (загрузка сцены, переходы)
Повторить snapshot
Найти растущие классы Cesium:
Проверить retainers до глобальных объектов (window,
viewer)
Проверить наличие забытых event listeners