Кэширование тайлов

Многоуровневая модель кэширования

В Mapbox GL JS кэширование тайлов строится как многоуровневая система, в которой участвуют браузер, сетевой слой, Web Worker-процессы и внутренние структуры движка рендеринга. Основная цель — минимизация повторных запросов к серверу и ускорение отрисовки карты при перемещении и масштабировании.

Ключевые уровни:

  • HTTP-кэш браузера (disk/memory cache)
  • внутренний кэш источников данных (Source Cache)
  • кэш тайлов в стиле (Tile Cache)
  • кэш растровых текстур (для raster layers)
  • кэш глифов (шрифтов)
  • кэш спрайтов (icons/sprites)

Каждый уровень работает независимо, но согласованно через идентификаторы тайлов и систему координат z/x/y.


Идентификация тайлов и базовый принцип повторного использования

Каждый тайл в Mapbox GL JS определяется тройкой координат:

  • z — уровень масштабирования
  • x — индекс по горизонтали
  • y — индекс по вертикали

Эта система формирует уникальный ключ тайла. При любом изменении центра карты или масштаба движок проверяет наличие тайла в кэше перед тем, как инициировать загрузку.

Дополнительно используется нормализация координат:

  • учёт wrap-around по долготе
  • приведение к каноническому виду (canonical tile coordinates)
  • дедупликация одинаковых тайлов, отображаемых в разных частях мира

Это позволяет повторно использовать один и тот же тайл при прокрутке мира по горизонтали.


Source Cache: первый слой внутреннего хранения

Source Cache отвечает за хранение уже загруженных тайлов внутри конкретного источника данных (source).

Для vector tiles:

  • хранит распарсенные protobuf-данные
  • содержит геометрии features
  • сохраняет свойства (properties)
  • индексирует данные для фильтрации и стилевых выражений

Для raster tiles:

  • хранит декодированные изображения
  • может удерживать текстуры в GPU-памяти

Повторное использование Source Cache исключает необходимость повторного парсинга данных при изменении стиля или повторном рендере.


Tile Cache: управление жизненным циклом тайлов

Tile Cache управляет активными тайлами, которые участвуют в текущем кадре отрисовки.

Основные характеристики:

  • ограниченный размер (LRU-стратегия)
  • приоритет активных viewport-тайлов
  • вытеснение наименее используемых элементов
  • привязка к zoom-диапазону слоя

Алгоритм работы:

  1. Запрос тайла по z/x/y
  2. Проверка Tile Cache
  3. При попадании — использование без сетевого запроса
  4. При промахе — обращение к Source Cache или загрузка с сервера

LRU-эвикция особенно важна при плавном pan/zoom, где количество потенциально видимых тайлов резко увеличивается.


HTTP-кэширование и CDN-уровень

Перед тем как данные попадают в Mapbox GL JS, они обрабатываются HTTP-кэшем браузера.

Используются стандартные механизмы:

  • Cache-Control (max-age, immutable)
  • ETag
  • Last-Modified
  • CDN edge caching

Mapbox tile URLs обычно включают версионирование стиля или источника данных, что делает тайлы фактически неизменяемыми:

  • обновление стиля → новый URL → новый кэш
  • старые тайлы остаются в кеше до истечения TTL

Это позволяет достигать высокой степени попадания в cache hit ratio даже при частых перемещениях карты.


Кэширование в Web Worker архитектуре

Mapbox GL JS использует Web Workers для обработки тайлов и рендеринга данных вне main thread.

В этом контексте кэширование разделяется:

  • Worker Tile Cache — хранит загруженные и декодированные тайлы
  • Main Thread Cache — хранит ссылки на готовые данные для рендера
  • Transferable objects — минимизируют копирование данных

Векторные тайлы после декодирования передаются через structured cloning или transferables, что снижает нагрузку на память.


Кэширование растровых данных

Raster tiles требуют отдельного слоя кэширования, так как они уже содержат готовые изображения.

Особенности:

  • хранение как ImageBitmap или WebGL texture
  • повторное использование GPU-текстур
  • ограничение по видеопамяти
  • приоритет видимых тайлов

При нехватке памяти старые текстуры удаляются из GPU cache, но могут оставаться в HTTP cache для повторной загрузки.


Кэширование глифов (шрифтов)

Глифы загружаются отдельными тайлами шрифтов, обычно в формате PBF.

Механизм:

  • запрос glyph range (например, 0–255)
  • кэширование диапазона символов
  • повторное использование между стилями

Glyph cache особенно эффективен в многоязычных картах, где одинаковые символы используются многократно.


Кэш спрайтов (icons и symbols)

Спрайты загружаются как единый atlas:

  • JSON-описание
  • PNG или WebP изображение

Кэширование включает:

  • хранение atlas в памяти
  • декодированные sub-images
  • reuse между слоями

При смене стиля спрайты могут полностью заменяться, но браузерный HTTP cache часто предотвращает повторную загрузку.


Инвалидация кэша и обновление данных

Кэш в Mapbox GL JS не предполагает частую инвалидацию на уровне отдельных тайлов. Вместо этого используется модель версионирования:

  • изменение источника данных → новый URL
  • изменение стиля → новый style JSON
  • изменение tileset → новый endpoint

Дополнительно:

  • ETag заставляет браузер запрашивать актуальность
  • max-age контролирует срок жизни тайлов
  • stale-while-revalidate позволяет использовать устаревшие тайлы временно

Предзагрузка тайлов (tile preloading)

Mapbox GL JS может загружать тайлы заранее на основе текущего viewport.

Механизмы:

  • расширенный bounding box (buffer around viewport)
  • предиктивная загрузка при inertia pan
  • загрузка тайлов соседних zoom уровней

Это снижает вероятность “пустых зон” при быстром перемещении карты.


Ограничение памяти и эвикция

Так как количество тайлов растёт экспоненциально с zoom, используется строгая политика очистки:

  • LRU eviction для Tile Cache
  • ограничение max tile count
  • приоритет visible tiles
  • освобождение GPU ресурсов

При этом Source Cache может сохраняться дольше Tile Cache, так как парсинг vector tiles дорог.


Offline-кэширование и локальное хранение

Для офлайн-сценариев используется комбинация:

  • IndexedDB (основное хранилище тайлов)
  • Service Worker (перехват запросов)
  • локальные tile packs

Модель работы:

  1. заранее загружается набор тайлов
  2. сохраняется в IndexedDB
  3. Service Worker перехватывает tile request
  4. возвращает локальные данные вместо сети

Это позволяет полностью изолировать карту от сетевого доступа.


Оптимизация кэширования через конфигурацию источников

Mapbox GL JS позволяет влиять на поведение кэша через параметры source:

  • minzoom / maxzoom — ограничение диапазона тайлов
  • bounds — ограничение географии загрузки
  • tileSize — влияние на плотность кэша
  • volatile sources — временные данные без длительного хранения

Чем точнее ограничен источник, тем эффективнее используется кэш.


Влияние стилей на эффективность кэша

Стиль напрямую влияет на повторное использование тайлов:

  • одинаковые source-layer структуры увеличивают hit ratio
  • фильтры, не меняющие геометрию, сохраняют кэш
  • выражения layout/paint не инвалидируют тайлы, если данные те же

Кэширование работает на уровне данных, а не визуального представления, что позволяет одному тайлу использоваться в разных стилях.


Дедупликация запросов тайлов

Внутренний request manager Mapbox GL JS предотвращает дублирование запросов:

  • один tile request на z/x/y в момент времени
  • очереди ожидания подписываются на один результат
  • отмена лишних запросов при изменении viewport

Это снижает нагрузку на сеть при быстром pan/zoom.


Связь кэширования и производительности рендера

Эффективное кэширование напрямую влияет на:

  • FPS при перемещении карты
  • время первого рендера
  • плавность zoom transition
  • нагрузку на CPU и GPU

Основной выигрыш достигается за счёт:

  • уменьшения сетевых запросов
  • сокращения парсинга vector tiles
  • повторного использования WebGL текстур
  • снижения GC pressure в JS-движке