Внутренняя модель памяти в Mapbox GL JS опирается на несколько уровней: JavaScript-объекты (карта, стиль, источники данных), WebGL-ресурсы (буферы, текстуры, шейдеры), worker-потоки (парсинг тайлов, генерация геометрии) и кэш тайлов. Каждый из этих уровней может становиться источником утечек, если жизненный цикл карты не синхронизирован с освобождением ресурсов.
Экземпляр карты удерживает значительное количество связей:
Ключевой особенностью является то, что значительная часть памяти выходит за пределы GC JavaScript и находится в WebGL/браузерных подсистемах.
WebGL-слой формирует объекты, которые не видны напрямую в JavaScript heap:
Эти ресурсы освобождаются только при корректном уничтожении контекста. Потеря ссылки в JS не гарантирует освобождение GPU-памяти.
Tile cache — одна из наиболее динамичных частей системы. При перемещении карты:
Если карта долго живёт в интерактивном режиме, кэш может стабилизироваться, но при частых сменах стилей или источников возникает фрагментация памяти.
Основной метод анализа — heap snapshot в Chrome DevTools. При работе с Mapbox GL JS полезно фиксировать три состояния:
Разница между этими состояниями позволяет выявить удерживаемые объекты.
Особое внимание:
MapStyleTileНаиболее типичные проблемы:
1. Не вызван map.remove()
Без явного удаления карты остаются:
const map = new mapboxgl.Map({ container: 'map' });
// при удалении компонента
map.remove();
2. Утечки через обработчики событий
function onMove() {
console.log('move');
}
map.on('move', onMove);
// отсутствие cleanup
map.off('move', onMove);
Даже небольшие closures удерживают ссылки на внешние данные.
3. Динамическое добавление слоёв без удаления
map.addLayer({
id: 'points',
type: 'circle',
source: 'points-data'
});
// при повторных рендерах без removeLayer происходит накопление
Помимо heap snapshot, существует логическая “снимковая” модель состояния карты — сериализация стиля:
const styleSnapshot = map.getStyle();
Этот объект включает:
Такой снимок используется для:
Однако он не отражает WebGL или worker memory.
Методика анализа:
В DevTools важны показатели:
Особенно показательны объекты, которые сохраняются после
map.remove().
Mapbox GL JS активно использует Web Workers для:
Worker может удерживать память даже после удаления карты, если:
Это проявляется как “phantom memory”, не видимая в основном heap.
Текстуры символов и иконок агрегируются в атласы. При динамической смене стиля:
Это объясняет ситуации, когда JavaScript heap стабилен, но использование памяти процесса растёт.
Корректное освобождение ресурсов включает последовательность:
map.remove()function destroyMap(map) {
map.getStyle().layers.forEach(layer => {
if (map.getLayer(layer.id)) {
map.removeLayer(layer.id);
}
});
Object.keys(map.getStyle().sources).forEach(sourceId => {
if (map.getSource(sourceId)) {
map.removeSource(sourceId);
}
});
map.remove();
}
Инструменты:
performance.memory (ограниченно)Признаки утечки:
В устойчивых сценариях карта должна:
В противном случае наблюдается линейный рост памяти, особенно при
частых setStyle() вызовах.
Снимки памяти позволяют фиксировать:
В инженерных процессах сравнение snapshot diff становится эквивалентом тестирования состояния рендера, особенно при сложных интерактивных сценах с большим количеством источников и слоёв.