Performance API

Performance в Mapbox GL JS опирается на комбинацию возможностей браузерного Performance API, внутреннего рендер-цикла WebGL и событийной модели загрузки источников данных. Основная задача слоя производительности — обеспечить измеримость каждого этапа: от запроса тайла до финального кадра, от парсинга стиля до выполнения отрисовки в WebGL-контексте.

Внутри Mapbox GL JS производительность не является отдельным модулем, а распределена между несколькими уровнями:

  • браузерный performance (High Resolution Time API)
  • WebGL render loop (requestAnimationFrame)
  • worker-потоки (parsing vector tiles)
  • event-driven pipeline источников данных
  • внутренние метрики кадра (frame metrics)

Ключевая идея заключается в том, что каждый этап рендеринга карты можно представить как цепочку измеряемых операций: загрузка данных → подготовка геометрии → компиляция стиля → рендер кадра.

Browser Performance API и интеграция

Базовый инструмент измерения — window.performance. Он используется для:

  • измерения времени загрузки ресурсов (тайлы, спрайты, шрифты)
  • фиксирования пользовательских меток (performance.mark)
  • вычисления длительности этапов (performance.measure)
  • анализа сетевых задержек через Resource Timing API

Mapbox GL JS активно опирается на эти данные при включении режима сбора метрик ресурсов.

Типовой сценарий включает:

  • фиксацию момента запроса тайла
  • фиксацию момента получения ответа
  • вычисление latency загрузки
  • сопоставление с кадром рендеринга

Метрики рендер-цикла

Рендер-контур карты работает в рамках requestAnimationFrame. Каждый кадр можно логически разделить на стадии:

  • обработка изменений состояния карты (zoom, pan, bearing)
  • проверка необходимости перерисовки
  • обновление источников данных
  • построение WebGL команд
  • финальная отрисовка кадра

Внутренне Mapbox GL JS отслеживает:

  • длительность кадра (frame time)
  • количество отрисованных тайлов
  • количество WebGL draw calls
  • время ожидания GPU (через косвенные оценки)

Если frame time превышает ~16.67ms (60 FPS), начинается деградация плавности интерфейса.

showPerformanceMetrics и отладочные показатели

Встроенный механизм отображения метрик активируется через опции карты:

  • FPS (кадры в секунду)
  • количество активных тайлов
  • количество загруженных ресурсов
  • memory usage WebGL контекста
  • время рендеринга кадра

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

Пайплайн загрузки источников данных

Производительность сильно зависит от типа источников:

Vector Tiles

  • парсятся в worker thread
  • декодируются из MVT формата
  • преобразуются в геометрию WebGL буферов

Основные затраты:

  • JSON/Protobuf decoding
  • geometry simplification
  • feature filtering по стилям

Raster Tiles

  • загружаются как изображения
  • минимальная CPU нагрузка
  • основной bottleneck — сеть и декодирование изображения

GeoJSON sources

  • парсятся полностью на стороне клиента
  • могут блокировать main thread при больших объёмах

Узкие места рендеринга

Производительность чаще всего ограничивается не одной причиной, а комбинацией факторов:

Геометрическая сложность

Большое количество вершин увеличивает:

  • время загрузки в GPU buffers
  • время обработки vertex shader
  • нагрузку на memory bandwidth

Количество слоёв стиля

Каждый слой в стиле Mapbox GL JS может:

  • выполнять фильтрацию
  • участвовать в компоновке
  • генерировать отдельные draw calls

Layout и paint фазы

  • layout: вычисление позиционирования символов и линий
  • paint: применение визуальных свойств

Layout особенно дорог для symbol layers (тексты, иконки).

Web Workers и параллелизм

Ключевая особенность архитектуры — вынос тяжёлых операций в Web Workers:

  • парсинг векторных тайлов
  • генерация геометрии
  • подготовка data-driven стилей

Это снижает нагрузку на main thread и уменьшает jank при взаимодействии с UI.

Однако существует ограничение: передача данных между потоками через structured clone также имеет стоимость.

Caching и повторное использование данных

Производительность сильно зависит от стратегий кэширования:

  • tile cache (геометрия тайлов)
  • glyph cache (шрифтовые глифы)
  • sprite cache (иконки)
  • style cache (интерпретированные выражения)

Эффективный кэш снижает:

  • количество сетевых запросов
  • повторный парсинг данных
  • повторную компиляцию стилей

Query API и влияние на FPS

Методы выборки данных, такие как hit-testing и spatial queries, могут быть критичными:

  • queryRenderedFeatures
  • querySourceFeatures

Стоимость зависит от:

  • количества слоёв
  • сложности фильтров
  • текущего zoom level
  • плотности данных на экране

При частых вызовах (например, mousemove) такие операции становятся заметным источником нагрузки.

GPU и WebGL ограничения

Mapbox GL JS полностью зависит от WebGL, поэтому производительность определяется GPU-пайплайном:

  • vertex throughput
  • fragment shader complexity
  • texture bandwidth
  • state switching (bind/unbind)

Особенно дорого:

  • большое количество текстур (glyph atlas, sprites)
  • прозрачные слои (overdraw)
  • сложные выражения в paint properties

Тайминги событий карты

Событийная модель карты даёт косвенные метрики производительности:

  • load — завершение начальной загрузки стиля
  • idle — отсутствие активных задач рендеринга
  • render — каждый кадр рендеринга
  • data / sourcedata — изменения источников

Интервал между render и idle позволяет оценить, насколько карта перегружена текущими задачами.

Оптимизация через стиль и источники

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

  • минимизация количества слоёв
  • агрегация данных на серверной стороне
  • упрощение геометрии до загрузки
  • ограничение maxzoom/minzoom для слоёв

Также критично уменьшение избыточных выражений (expressions) в стиле, особенно при data-driven styling.

Memory pressure и утечки

Основные источники памяти:

  • кешированные тайлы
  • геометрические буферы WebGL
  • растровые текстуры
  • декодированные GeoJSON структуры

При высокой нагрузке возможны:

  • рост WebGL memory usage
  • фрагментация буферов
  • деградация FPS при длительной работе

Итоговая модель производительности

Производительность Mapbox GL JS можно рассматривать как систему из трёх взаимодействующих слоёв:

  • сетевой слой (тайлы, ресурсы)
  • CPU слой (парсинг, layout, JS execution)
  • GPU слой (рендеринг кадра)

Баланс между ними определяет стабильность FPS и отзывчивость карты, при этом узкое место может возникнуть на любом этапе цепочки — от запроса тайла до финального fragment shader.