Профилирование передачи данных

Модель передачи данных и точки измерения

STOMP.js работает поверх WebSocket и передаёт данные в виде текстовых кадров STOMP-протокола. Каждый кадр включает команду, заголовки и тело сообщения. При профилировании передачи данных важно учитывать, что фактическая стоимость коммуникации складывается из нескольких уровней:

  • WebSocket-фреймирование на транспортном уровне
  • STOMP-кадры (заголовки + тело сообщения)
  • Сериализация полезной нагрузки (JSON, бинарные строки, base64)
  • Повторные доставки при переподключении
  • Подписочная модель (fan-out на брокере)

Ключевые точки измерения:

  • задержка доставки сообщения (end-to-end latency)
  • размер STOMP-фрейма
  • пропускная способность (messages per second)
  • накладные расходы на соединение (handshake + heart-beat)
  • время обработки сообщений клиентом

Измерение задержек доставки сообщений

Задержка передачи в STOMP-системе должна измеряться на нескольких этапах:

  1. Время отправки сообщения клиентом
  2. Время попадания в брокер
  3. Время маршрутизации по топику или очереди
  4. Время доставки обратно клиенту
  5. Время обработки callback-ом subscribe

Практически применяемая схема меток времени:

  • clientSendTime
  • brokerReceiveTime (если доступно)
  • brokerDispatchTime
  • clientReceiveTime

Разница между clientSendTime и clientReceiveTime даёт end-to-end latency.

Особое внимание следует уделять jitter — разбросу задержек. Даже при низком среднем значении латентности система может быть нестабильной при пиковых нагрузках.


Анализ размера STOMP-фреймов

STOMP.js передаёт данные в текстовом виде, поэтому размер сообщения напрямую влияет на производительность сети и парсинг.

Структура типичного кадра:

SEND
destination:/topic/chat
content-type:application/json

{"message":"hello"}
\0

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

  • повторяющиеся заголовки (destination, content-type)
  • JSON-сериализация
  • терминатор кадра (\0)
  • UTF-8 кодирование

При профилировании фиксируются:

  • средний размер кадра
  • максимальный размер (outliers)
  • распределение по типам сообщений
  • доля заголовков в общем объёме

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


Пропускная способность и нагрузочное поведение

Пропускная способность STOMP.js определяется узким местом между клиентом, сетью и брокером.

Метрики throughput:

  • messages/sec на клиенте
  • messages/sec на брокере
  • aggregate bandwidth (bytes/sec)
  • количество активных подписок

Типичный профиль деградации:

  • при низкой нагрузке рост линейный
  • при достижении порога сети наблюдается резкий рост latency
  • далее начинается очередь сообщений на брокере

Важно учитывать, что WebSocket сам по себе не ограничивает поток, поэтому backpressure реализуется на уровне приложения или брокера.


Профилирование подписок и fan-out

Модель подписок в STOMP основана на топиках. Один опубликованный кадр может быть доставлен множеству клиентов.

Стоимость fan-out зависит от:

  • количества подписчиков на destination
  • сложности маршрутизации в брокере
  • размера сообщения
  • политики доставки (persistent / non-persistent)

Метрики:

  • время доставки одного сообщения всем подписчикам
  • деградация при увеличении числа подписок
  • нагрузка на GC из-за копирования сообщений

При большом количестве подписчиков критично измерять не только среднюю задержку, но и хвост распределения (p95, p99).


Heart-beat и его влияние на трафик

STOMP.js поддерживает механизм heart-beat для контроля живости соединения. Он состоит из периодических пустых кадров.

Профилируемые параметры:

  • частота отправки heartbeat
  • размер контрольных кадров
  • влияние на общий трафик при idle-соединениях

При высокой частоте heartbeat создаётся постоянный фон трафика, который может быть значим при тысячах соединений.


Сетевые узкие места и влияние WebSocket слоя

Хотя STOMP работает на уровне протокола сообщений, транспорт WebSocket оказывает существенное влияние:

  • TLS-рукопожатие при установке соединения
  • TCP slow start
  • влияние потерь пакетов на ретрансляцию
  • head-of-line blocking

При профилировании важно разделять:

  • задержки транспортного уровня
  • задержки брокера
  • задержки обработки в браузере

Профилирование сериализации и десериализации

Основная нагрузка на клиенте возникает при:

  • JSON.parse входящих сообщений
  • JSON.stringify исходящих сообщений
  • обработке callback-ов подписки

Метрики:

  • время парсинга одного сообщения
  • CPU usage при высокой частоте сообщений
  • влияние крупных payload на event loop

Оптимизационный эффект достигается при уменьшении глубины объектов и отказе от избыточных структур данных.


Очереди сообщений и поведение при перегрузке

При перегрузке системы формируются очереди:

  • на стороне брокера (internal queue)
  • на стороне клиента (message buffer)
  • на уровне TCP стеков

Симптомы перегрузки:

  • рост latency без увеличения throughput
  • рост memory usage в браузере
  • задержка обработки подписок

Профилирование требует фиксации:

  • длины очереди сообщений
  • времени жизни сообщения в очереди
  • частоты дропов (если брокер применяет ограничение)

Инструменты наблюдения в браузере

Для анализа STOMP.js на клиенте используются:

  • Performance API (User Timing)
  • Network tab в DevTools (WebSocket frames)
  • Memory profiling (heap snapshots)
  • Event loop lag measurement

Практический подход:

  • логирование timestamp на каждом этапе обработки сообщения
  • измерение времени между onMessage и завершением обработки callback
  • анализ блокировок main thread

Корреляция нагрузки и поведения системы

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

  • линейное масштабирование до определённого порога
  • экспоненциальный рост задержек после saturation point
  • нестабильность при burst-трафике

Фиксируются зависимости:

  • messages/sec → latency
  • number of subscriptions → CPU usage
  • payload size → throughput

Эффекты накопления нагрузки при длительной работе

Долгоживущие соединения STOMP.js требуют анализа долговременных эффектов:

  • утечки памяти при некорректном unsubscribe
  • рост числа активных handler-ов
  • деградация GC при большом количестве объектов сообщений

Особенно заметно при:

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

Профилирование повторных подключений

При разрывах соединения STOMP.js выполняет reconnect, который включает:

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

Метрики:

  • время восстановления соединения
  • количество потерянных сообщений
  • нагрузка при массовом reconnect (thundering herd effect)

Анализ распределения задержек

Средние значения латентности недостаточны для анализа. Важны:

  • p50 (медиана)
  • p95 (основной пользовательский опыт)
  • p99 (краевые случаи)

Длинный хвост распределения часто возникает из-за:

  • GC пауз в браузере
  • перегрузки брокера
  • сетевых ретрансляций

Итоговая модель наблюдаемого потока данных

Система передачи данных STOMP.js может быть представлена как цепочка:

клиент → WebSocket → STOMP broker → routing → fan-out → WebSocket → клиент → обработка callback

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