Mapbox GL JS использует WebGL как основной слой отрисовки, что означает распределение памяти между JavaScript-heap и GPU-памятью. Эти две области нельзя анализировать одинаково: стандартные инструменты браузера видят только часть картины.
JavaScript-объекты (карта, источники, стили, события) живут в heap V8, тогда как геометрия тайлов, текстуры, спрайты и glyph-атласы размещаются в виде GPU-ресурсов. Это создаёт ключевую особенность: утечки могут происходить даже при «чистом» JavaScript-heap, если не освобождаются WebGL-ресурсы.
Mapbox GL JS дополнительно использует Web Workers для парсинга векторных тайлов и подготовки данных к рендерингу. Эти воркеры имеют собственные буферы и кэш, который не всегда очевиден при стандартном профилировании.
Каждый загруженный тайл декодируется и сохраняется в памяти для повторного использования. Кэш тайлов является одной из крупнейших статей потребления памяти.
Рост памяти происходит при:
sources)maxzoom и плотности данныхКэширование ускоряет работу, но при длительных сессиях может приводить к накоплению значительных объёмов данных.
Растровые слои создают текстуры в GPU. Каждое изображение тайла преобразуется в texture object. Утечки часто возникают при:
raster-sourcemap.remove()Текстуры не всегда немедленно освобождаются сборщиком мусора JavaScript, так как управляются WebGL-контекстом.
Mapbox GL JS использует подписные наборы шрифтов, которые загружаются в виде glyph atlas — специальных текстур, содержащих символы.
Проблемные сценарии:
text-field с разными наборами
символовGlyph atlas может занимать значительный объём GPU памяти, особенно при наличии CJK-символов.
Sprite atlas — ещё один крупный источник памяти. Он содержит иконки и изображения стиля.
Ключевая проблема возникает при:
addImage() без
removeImage()Каждое изображение упаковывается в текстуру, которая остаётся в GPU до уничтожения стиля или карты.
Наиболее частая проблема — создание нового mapboxgl.Map
без уничтожения предыдущего экземпляра.
Даже если DOM-узел удалён, WebGL-контекст может оставаться активным, если не вызвано:
map.remove();
Без этого вызова:
Слушатели событий могут удерживать ссылки на карту и связанные объекты.
Особенно критично:
map.on('move', ...)map.on('render', ...)Если обработчики создаются внутри функций без последующего
off, возникает классическая утечка через closure.
Добавление и удаление источников (addSource,
removeSource) влияет на память несимметрично.
Типичная проблема:
Особенно заметно при frequent updates GeoJSON sources.
Основной инструмент — вкладка Memory:
Важно учитывать, что WebGL ресурсы не всегда видны в heap snapshot.
Позволяет анализировать:
При аномалиях можно заметить постоянные пересоздания tile objects, что косвенно указывает на проблемы кэша.
Дополнительные инструменты браузера позволяют отслеживать:
В некоторых случаях полезно использовать расширения для отслеживания WebGL calls.
Частая операция:
map.setStyle('mapbox://styles/...')
Проблема возникает, когда предыдущий стиль не полностью освобождает:
При многократной смене стилей наблюдается рост GPU памяти.
При использовании Mapbox GL JS внутри компонентных систем типична ошибка:
useEffectЭто приводит к накоплению WebGL контекстов при повторных рендерах компонентов.
GeoJSON источники, обновляемые каждую секунду (например, трекинг объектов), могут:
Особенно критично при использовании setData без контроля
размера данных.
Базовая стратегия — строгое управление жизненным циклом:
map.remove() при уничтожении картыremoveImageMapbox GL JS позволяет контролировать кэширование через параметры источников и стратегии загрузки.
Снижение памяти достигается за счёт:
maxzoomВместо пересоздания объектов предпочтительно:
setDataВысокочастотные обновления (например, анимации или live data) требуют:
Поведение приложения часто даёт больше информации, чем инструменты:
Особенно характерен сценарий, при котором перезагрузка страницы временно «исправляет» проблему — это почти всегда утечка ресурсов.
WebGL контекст имеет ограничение на число активных контекстов в браузере. При превышении лимита:
too many WebGL contextsЭто делает корректное уничтожение карт критически важным элементом архитектуры приложений на Mapbox GL JS.