Перейти к содержимому
Star

Производительность ​

deffector работает поверх инспектора ядра effector: он видит каждый шаг каждой транзакции. Это не бесплатно, поэтому агент аккуратно выбирает, когда писать.

Пауза, пока DevTools закрыты ​

По умолчанию (whileClosed: 'pause'):

  1. После загрузки агент пишет graceMs — 10 секунд. Если открыть DevTools за это время, начало страницы будет в логе.
  2. Если к этому моменту панель не подключилась, агент встаёт на паузу: отбрасывает записанное и перестаёт писать. Шаги продолжает считать только аварийная остановка.
  3. Когда панель подключается, запись продолжается с текущего состояния. Health пишет «История до открытия панели не записана».
  4. Когда панель отключается, агент ждёт 3 секунды (за это время перезапущенный service worker расширения успевает переподключиться) и снова встаёт на паузу.

Чтобы записать начало страницы, откройте DevTools и перезагрузите её. Чтобы писать всегда, задайте attachDeffector({ whileClosed: 'record' }).

На паузе хук ядра сразу возвращается, посчитав шаг для аварийной остановки: ничего не собирается, не анализируется и не отправляется. (Кнопка Остановить запись в панели — другое: панель подключена, транзакции не хранятся, но их изменения состояния складываются в базу, чтобы последующие переходы оставались верными.)

Сколько это стоит ​

Замеры в демо-лаборатории (demo/lab) на графах примерно из 1 000, 5 000 и 20 000 юнитов, где одно действие проходит через каждый юнит:

РежимСтоимость одного действия
без агента (?noagent)базовая
агент установлен, на паузепримерно как без агента
запись, панель открытапримерно в 3–7 раз дороже базовой

Запись — это зарегистрировать каждый юнит, положить каждый шаг в транзакцию с лейном, родителем и значениями, найти двойные обновления, устаревшее чтение и остановленные filter, сохранить изменения сторов для перемещения во времени и отправить всё это в панель. В обычных приложениях действие — это несколько десятков шагов, и разница незаметна; на цепочке из 20 000 юнитов — заметна.

Измерить на своей машине:

sh
npm run dev:lab                                         # http://localhost:5178
PERF=perf.json npx playwright test e2e/perf.spec.ts     # записывает числа в perf.json

Тест сравнивает ?noagent, агента на паузе (?grace=200) и запись, а ещё замеряет, сколько панель подключается и рисует граф.

Ограничения, которые держат память ровной ​

НастройкаПо умолчаниюДействие
maxTransactions1000длина истории; более старые транзакции удаляются
maxSteps5000шагов на транзакцию; остаток огромной транзакции не хранится
Не записывать—шумные транзакции хранят только изменения состояния и не отправляются

В панели лог рисует только видимые строки, палитра ищет по последним 300 транзакциям, а Graph рисует не больше 120 юнитов, пока вы не попросите больше.

Аварийная остановка ​

Событие, которое вызывает само себя через sample или watcher, никогда не заканчивается: у цикла ядра effector нет ограничения, и вкладка зависает. deffector считает шаги в каждом синхронном проходе ядра; после hardStop (100 000) он обрывает распространение: каждый узел, выполненный сверх лимита, перестаёт передавать значения дочерним, ядро опустошает очередь и возвращает управление, а на следующей микрозадаче deffector возвращает связи на место. Вкладка жива, приложение продолжает работать, а:

  • транзакция в логе помечается остановлено;
  • Health показывает deffector остановил бесконечный цикл с самыми частыми юнитами и кнопкой Показать в Graph;
  • в консоль пишется [deffector] deffector остановил бесконечный цикл: … (на языке панели).

Состояние может быть частично обновлено циклом. Остановка работает и на паузе. hardStop: false отключает её, а большее число подойдёт, если приложение законно выполняет больше шагов за раз.

Отдельно циклы только через события находятся в статическом графе и попадают в Health ещё до того, как выполнятся.

Продакшен ​

Каждая точка входа через условие экспорта production становится пустышкой, а @deffector/agent/node вдобавок проверяет NODE_ENV. Ничего не подключается и не записывается. См. Установка.

Страницы без агента ​

Content script расширения работает на localhost и на разрешённых сайтах и открывает соединение с расширением только после того, как агент страницы подаст голос, поэтому страницы без effector ничего не теряют.