Телефон: 8-800-350-22-65
Напишите нам:
WhatsApp:
Telegram:
MAX:
Прием заявок круглосуточно
График работы офиса: с 9:00 до 21:00 Нск (с 5:00 до 19:00 Мск)

Статья опубликована в рамках: Научного журнала «Студенческий» № 18(356)

Рубрика журнала: Информационные технологии

Библиографическое описание:
Прохоров Д.М. ОПТИМИЗАЦИЯ РЕНДЕРИНГА В ВЕБ-ПРИЛОЖЕНИЯХ: ФОРМАЛЬНАЯ МОДЕЛЬ ПРОИЗВОДИТЕЛЬНОСТИ РЕАКТИВНЫХ ПОЛЬЗОВАТЕЛЬСКИХ ИНТЕРФЕЙСОВ БЕЗ VIRTUAL DOM // Студенческий: электрон. научн. журн. 2026. № 18(356). URL: https://sibac.info/journal/student/356/416909 (дата обращения: 22.05.2026).

ОПТИМИЗАЦИЯ РЕНДЕРИНГА В ВЕБ-ПРИЛОЖЕНИЯХ: ФОРМАЛЬНАЯ МОДЕЛЬ ПРОИЗВОДИТЕЛЬНОСТИ РЕАКТИВНЫХ ПОЛЬЗОВАТЕЛЬСКИХ ИНТЕРФЕЙСОВ БЕЗ VIRTUAL DOM

Прохоров Дмитрий Максимович

студент, институт передовых информационных технологий, Тульский государственный педагогический университет,

РФ, г. Тула

Мартынюк Юлия Михайловна

научный руководитель,

канд. пед. наук, доц., Тульский государственный педагогический университет,

РФ, г. Тула

​Современные веб-приложения предъявляют высокие требования к производительности пользовательского интерфейса (UI). Объектная модель документа (DOM) является стандартным программным интерфейсом для взаимодействия с HTML-документами в браузере. Структура DOM представляет собой дерево, в корне которого находится объект Document, а узлами — элементы HTML-документа.

 

Рисунок 1. Структура DOM-дерева веб-документа

 

Операции изменения DOM (вставка, удаление, обновление узлов) ресурсоёмки: каждая мутация может вызывать перерасчёт стилей, перекомпоновку (reflow) и перерисовку (repaint) страницы. Для решения проблемы частых обновлений DOM в React был предложен подход Virtual DOM — легковесное объектное представление дерева компонентов в памяти [2]. При каждом изменении состояния React создаёт новый Virtual DOM, сравнивает его с предыдущим (reconciliation) и применяет минимальный набор мутаций к реальному DOM. Данный подход имеет фундаментальное ограничение: алгоритм reconciliation обходит всё виртуальное поддерево при каждом обновлении, даже если изменился единственный узел. Как указывается в [4], для больших приложений «многочисленные изменения будут приводить к многократным пересозданиям отдельных поддеревьев и их проверкам с предыдущей версией».

Альтернативный подход fine-grained reactivity реализован в SolidJS [3] и Svelte [7]. В данной модели компилятор во время сборки статически анализирует зависимости между данными (сигналами) и DOM-элементами, создавая прямые привязки. При изменении сигнала обновляются только подписанные на него DOM-узлы, без обхода остального дерева [3]. Цель работы — построение формальной модели стоимости обновления UI для обоих подходов и её верификация экспериментальными данными.

1. Теоретическая модель

Подход Virtual DOM основан на поддержании облегчённого представления DOM-дерева. При вызове setState запускается алгоритм reconciliation, рекурсивно сравнивающий каждый узел нового дерева со старым [2]. Суммарная стоимость I обновлений вычисляется по формуле:

где — размер виртуального поддерева при i-м обновлении. Для однородного списка из n элементов сложность одного обновления составляет O(n).

В SolidJS компилятор создаёт граф зависимостей, связывающий каждый сигнал с конкретными DOM-узлами [3]. При вызове setSignal(v) уведомляются только k прямых подписчиков:

Для типичного случая () сложность составляет O(k), где . Теоретическое ускорение в этом случае может быть вычислено по формуле:

При n = 1000 и k = 1 теоретическое ускорение рассчитывается как произведение 1000 на число посещённых узлов. При пакетном обновлении всех n элементов () оба подхода выполняют O(n) работы, и разница определяется лишь константными факторами.

2. Методика эксперимента

Для верификации модели разработаны два приложения на React 19.2.5 и SolidJS 1.9.12, собираемых Vite 8. Среда выполнения: Node.js v22, macOS, Apple M-серии; браузерные тесты — Chromium (headless, Playwright).

Таблица 1.

Сравнительная характеристика экспериментальной среды и используемых технологий

Параметр

React

SolidJS

Фреймворк

React 19.2.5

SolidJS 1.9.12

Роутер

react-router-dom 7.14.1

@solidjs/router 0.16.1

Сборщик

Vite 8

Vite 8

 

Проведены четыре серии экспериментов:

1) оценка размера production-бандла (npm run build);

2) алгоритмическая симуляция в Node.js: 1000 одиночных обновлений при N от 100 до 10 000, 10 прогонов после 3 warmup;

3) браузерный бенчмарк точечных обновлений: 200 случайных обновлений одной строки из N, MutationObserver, mean ± σ по 10 прогонам;

4) бенчмарк пакетного обновления всех N элементов.

3. Результаты экспериментов

Production-сборка (эксперимент 1) выявила существенное различие в размере бандла:

Таблица 2.

Сравнение размеров production-бандлов React и SolidJS

Метрика

React

SolidJS

Разница

JS (gzip)

686,09 kB

18,96 kB

36,2X

CSS (gzip)

1,59 kB

1,47 kB

≈ 1X

Всего dist/

2,1 MB

84 KB

25,6X

 

Вклад чистого runtime: react + react-dom — ~42 kB gzip, solid-js — ~7 kB gzip (разница 6X). SolidJS-компилятор генерирует прямые DOM-инструкции во время сборки, устраняя необходимость в runtime-движке reconciliation [7]. Данные согласуются с js-framework-benchmark [5]: solid-js — 4,9 kB (brotli) против 16,4 kB у React hooks.

Алгоритмическая симуляция (эксперимент 2) подтвердила теоретическую формулу:

Таблица 3.

Результаты алгоритмической симуляции точечных обновлений UI

N

React (мс)

SolidJS (мс)

Ratio

Посещений React

Посещений SolidJS

100

0,522

0,166

3,1X

100 000

1 000

1 000

2,127

0,232

9,2X

1 000 000

1 000

5 000

10,669

1,224

8,7X

5 000 000

1 000

10 000

19,503

2,138

9,1X

10 000 000

1 000

 

При N = 10 000 SolidJS выполняет в 10 000 раз меньше операций сравнения на одно обновление, что точно соответствует формулам и при .

Браузерный бенчмарк точечных обновлений (эксперимент 3):

 

Таблица 4.

Производительность точечных DOM-обновлений в браузере

N

React (мс)

σ

SolidJS (мс)

σ

Ratio

100

33,29

0,28

32,84

0,15

1,01X

500

51,60

5,06

33,27

0,31

1,55X

1 000

83,23

0,35

33,06

0,33

2,52X

5 000

348,17

24,06

33,55

0,36

10,38X

 

Время обновления React растёт линейно с N (от 33 мс при N = 100 до 348 мс при N = 5000), тогда как время SolidJS остаётся константным (~33 мс). Число DOM-мутаций одинаково (200) — оба фреймворка применяют ровно необходимое количество изменений.

Профилирование памяти (JS heap delta): при N = 500–1000 React аллоцирует ~2,7–3,5 MB на VDOM-объекты, тогда как SolidJS стабильно потребляет ~110 KB вне зависимости от N (разница до 31,8X при N = 1000). При N = 100 overhead инициализации графа зависимостей SolidJS перевешивает стоимость VDOM-структур; граница пересечения — между N = 100 и N = 500.

Бенчмарк пакетного обновления (эксперимент 4): при обновлении всех N элементов разница составляет ≤ 1 % (React: 33,27–33,73 мс, SolidJS: 33,28–33,59 мс), подтверждая теоретическую границу паритета — оба подхода выполняют O(n) работы.

4. Анализ результатов

Ключевое различие между React и SolidJS состоит в стадии определения зависимостей. React реализует runtime-реактивность: при каждом изменении состояния выполняется reconciliation — рекурсивный обход виртуального дерева [2]. Данный подход универсален, однако вносит overhead, пропорциональный размеру дерева.

SolidJS реализует compile-time реактивность: компилятор анализирует JSX-шаблоны, определяет зависимости DOM-узлов от сигналов и генерирует инструкции прямого обновления [7]. Как описано в [3], в fine-grained reactive системе «updates are made to the targeted attribute that needs to be changed, avoiding broader and, sometimes unnecessary, updates». Данный подход соответствует принципу инкрементальных вычислений: старый результат обновляется инкрементально вместо повторного выполнения всего вычисления [4].

Независимый бенчмарк js-framework-benchmark [5] стабильно демонстрирует лидерство signal-based фреймворков (SolidJS, Svelte) над VDOM-фреймворками в задачах точечного обновления и потребления памяти. TC39 proposal «Signals» (Stage 1) [6] формализует примитивы Signal.State и Signal.Computed как стандартные конструкции JavaScript, что свидетельствует о признании signal-based модели на уровне стандарта языка. Интерпретация результатов требует учёта ограничений: тестировались конкретные версии фреймворков; бенчмарк использует синтетическую таблицу; профилирование памяти подвержено влиянию GC при больших N.

В настоящей работе предложена и экспериментально верифицирована формальная модель стоимости обновления UI для двух парадигм: Virtual DOM (React) и fine-grained reactivity (SolidJS). Математическую модель можно представить следующими формулами:

где n — размер виртуального поддерева, k — число подписчиков сигнала, .

Экспериментальная верификация подтвердила следующие положения: при точечных обновлениях SolidJS превосходит React до 10,4X при N = 5000; при пакетных обновлениях оба демонстрируют паритет (≤ 1 %); SolidJS потребляет в 31,8X меньше памяти при N = 1000. Преимущество fine-grained reactivity определяется compile-time графом зависимостей — runtime-dispatcher уведомляет только прямых подписчиков без обхода дерева [3, 7] — и отсутствием VDOM overhead: нет создания виртуальных объектов, двухфазного коммита и scheduler overhead [1]. Полученные результаты согласуются с js-framework-benchmark [5] и подтверждают индустриальный тренд к отказу от Virtual DOM, формализуемый через TC39 proposal Signals [6].

 

Список литературы:

  1. Почему реактивность без VDOM (с реальным DOM) лучше, чем реактивность с VDOM? // Habr. – б. г. – URL: https://habr.com/en/articles/803779/ (дата обращения: 15.04.2026).
  2. React и альтернативы // Дока. – б. г. – URL: https://doka.guide/tools/react-and-alternatives/ (дата обращения: 15.04.2026).
  3. Fine-grained reactivity // SolidJS Documentation. – б. г. – URL: https://docs.solidjs.com/advanced-concepts/fine-grained-reactivity (дата обращения: 15.04.2026).
  4. Freeman P. Incrementally Improving The DOM // Blog.functorial.com. – 2018. – URL: https://blog.functorial.com/posts/2018-04-08-Incrementally-Improving-The-DOM.html (дата обращения: 15.04.2026).
  5. Krause S. js-framework-benchmark // GitHub. – б. г. – URL: https://github.com/krausest/js-framework-benchmark (дата обращения: 15.04.2026).
  6. Ehrenberg D. TC39 Proposal: JavaScript Signals Standard (Stage 1) / D. Ehrenberg, R. Eisenberg, Y. Katz [и др.]. – 2024. – URL: https://github.com/tc39/proposal-signals (дата обращения: 15.04.2026).
  7. Understanding Compile-Time Reactivity in SolidJS and Svelte // Leapcell Blog. – б. г. – URL: https://leapcell.io/blog/understanding-compile-time-reactivity-in-solidjs-and-svelte (дата обращения: 15.04.2026).