Влияние количества правил на скорость

В основе работы ESLint лежит последовательный пайплайн обработки исходного кода: парсинг, построение AST (абстрактного синтаксического дерева), обход дерева и выполнение набора правил. Именно последний этап оказывает наибольшее влияние на итоговую скорость анализа.

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

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


Линейный рост нагрузки при добавлении правил

Поведение системы в простейшей модели можно описать как линейное:

  • N — количество правил
  • M — количество узлов AST

Общая нагрузка стремится к произведению N × M при условии, что каждое правило реагирует на схожий набор событий.

Однако реальная картина сложнее:

  • часть правил срабатывает только на конкретных типах узлов
  • часть правил выполняет предварительные фильтры
  • часть правил запускает дополнительные обходы дерева

Несмотря на оптимизации, увеличение количества активных правил почти всегда приводит к росту времени анализа.


Различие между «лёгкими» и «тяжёлыми» правилами

Правила в ESLint неоднородны по стоимости выполнения.

Лёгкие правила

К ним относятся проверки, которые:

  • работают только с локальными свойствами узла
  • не требуют анализа контекста программы
  • не обращаются к scope analysis

Примеры логики:

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

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


Тяжёлые правила

Сюда относятся проверки, которые:

  • используют анализ области видимости (scope tracking)
  • требуют построения графов зависимостей
  • обращаются к TypeScript-типам (через плагины)
  • выполняют повторные обходы AST

Особенно затратны правила, связанные с:

  • импортами и экспортами модулей
  • анализом использования переменных
  • проверкой потенциальных ошибок в асинхронном коде

Один такой rule может быть дороже десятков простых.


Влияние плагинов и расширенных наборов правил

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

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

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


Эффект «плотности правил»

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

Пример:

  • 5 правил обрабатывают CallExpression
  • 3 правила обрабатывают Identifier
  • 7 правил обрабатывают MemberExpression

Чем выше плотность, тем больше микрозатрат на один проход дерева. Даже при оптимальном алгоритме обхода AST увеличивается число вызовов функций, проверок условий и выделений памяти под контекст выполнения.


Влияние конфигурации и отключённых правил

Конфигурация ESLint влияет не только на включённые правила, но и на механизм их регистрации.

Полностью отключённые правила

Отключённые правила:

  • не участвуют в подписке на события AST
  • не создают обработчиков узлов
  • не влияют на runtime

Их наличие в конфигурации не увеличивает нагрузку.


Частично активные конфигурации

Некоторые конфигурации включают правила через условные механизмы:

  • overrides по файлам
  • разные наборы для production и development
  • динамические конфиги

В таких случаях увеличивается стоимость инициализации, но не всегда растёт runtime нагрузка на каждый файл.


Стоимость обработки одного файла

Время анализа одного файла можно разложить на компоненты:

  1. Парсинг исходного кода
  2. Построение AST
  3. Инициализация scope analysis
  4. Применение правил

При увеличении количества правил особенно растёт четвёртый этап. При этом первые три остаются относительно стабильными.

Если рассматривать большие проекты, то основная деградация происходит именно на этапе применения правил, а не парсинга.


Кэширование и его взаимодействие с количеством правил

Механизм cache в ESLint снижает повторную стоимость анализа неизменённых файлов, но не устраняет влияние количества правил.

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

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

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


Конкуренция правил за ресурсы обхода AST

Во время обхода AST один узел может быть обработан десятками правил. Каждый обработчик:

  • получает ссылку на узел
  • может запрашивать контекст scope
  • может выполнять вычисления и проверки

В итоге возникает конкуренция за:

  • CPU-время
  • память на временные структуры
  • результаты анализа scope

При увеличении числа правил растёт вероятность повторных вычислений одного и того же контекста.


Стоимость правил с побочными эффектами анализа

Некоторые правила требуют дополнительных проходов или сложного анализа:

  • построение графа импортов
  • анализ путей исполнения
  • проверка потенциальных runtime ошибок

Такие правила могут существенно увеличивать время анализа даже при небольшом их количестве. Влияние количества правил здесь нелинейно: добавление одного сложного правила иногда эквивалентно добавлению десятков простых.


Влияние порядка правил и группировки

Хотя ESLint не выполняет правила строго последовательно в смысле блокировки, порядок и группировка влияют на:

  • локальность кэширования
  • повторное использование scope
  • эффективность внутренних оптимизаций

Группировка тяжёлых правил в отдельных конфигурациях может уменьшить перекрёстные затраты, так как уменьшает число одновременных активных подписчиков на одни и те же узлы AST.


Масштабирование на уровне больших проектов

В крупных кодовых базах влияние количества правил проявляется сильнее:

  • увеличивается суммарное число узлов AST
  • растёт количество повторяющихся паттернов кода
  • возрастает нагрузка на scope analysis

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