ВВЕДЕНИЕ
С развитием веб-технологий и увеличением сложности веб-приложений вопрос оптимизации производительности становится одним из ключевых в задачах веб-разработки. Одним из наиболее ресурсоёмких аспектов при работе с веб-приложениями является визуальное отображение данных и интерфейсов пользователей. Браузерам приходится тратить значительные ресурсы процессорного времени и оперативной памяти для работы с Document Object Model (DOM) элементами, что может существенно влиять на скорость и отзывчивость веб-приложений.
В поисках решения этой проблемы разработчики и инженеры создали разнообразные подходы и технологии. Один из таких подходов - использование HTML элемента Canvas и связанного с ним Canvas API.
В данной статье мы рассмотрим сравнительный анализ использования DOM элементов и элемента Canvas в веб-разработке. Мы проанализируем преимущества и недостатки каждого подхода, а также предоставим количественные данные, демонстрирующие разницу в производительности и использовании ресурсов между ними [1].
ОСНОВНАЯ ЧАСТЬ
При работе с DOM элементами браузер тратит большое количество ресурсов компьютера: процессорного времени и оперативной памяти. Именно поэтому при работе с визуальными элементами разработчики стараются свести к минимуму обращение к DOM элементам или к их изменениям. Разработчики многих библиотек и фреймворков разработали для этих целей собственные решения. Так например разработчики одной их самой популярной библиотеки для frontend разработки – React, создали концепцию Virtual DOM. Согласно этому подходу все операции с DOM элементами происходят в оперативной памяти с их виртуальными упрощёнными версиями. Эти вносимые изменения происходят быстрее, чем с реальными DOM элементами. При этом применение внутренних алгоритмов оптимизации библиотеки React позволяет еще больше увеличить производительность веб-приложений.
Появление таких концепций, как Virtual DOM показывает актуальность проблемы медленной работы с DOM элементами в браузере. Однако использование даже самых совершенных алгоритмов не избавит от необходимости внесения изменений в DOM дерево. Применение подобных концепций лишь уменьшит количество обращений к DOM дереву.
Принципиально иной подход к отображению информации в браузере – использование HTML элемента Canvas, а также браузерного Canvas API для работы с ним. При использовании этого подхода программист имеет лишь один единственный DOM элемент и полный контроль над каждым его пикселем. С одной стороны это значительно увеличивает быстродействие веб-приложения, а с другой стороны усложняет логику работы и процесс разработки. При таком подходе разработчик сам отвечает за внешний вид и поведение приложения, в отличие от классического подхода с использованием DOM элементов, при котором все эти элементы управления уже реализованы на уровне браузера и операционной системы. Стоит также отметить, что для стилизации DOM-элементов программист может использовать CSS, а для анимаций - соответствующие средства из CSS: свойства “animation” и “transition”. Однако при использовании Canvas, разработчик вынужден самостоятельно стилизовать все визуальные элементы, создавать покадровую анимацию при помощи функции requestAnimationFrame из WebAPI [2], а также при необходимости самостоятельно создавать пользовательские компоненты и реализовывать реакции на каждое пользовательское событие [3].
Таким образом использование Canvas вместо классических DOM элементов имеет как преимущества в виде быстродействия итогового приложения, так и недостатки в виде увеличения сложности разработки.
Стоит также отметить, что при использовании элемента Canvas для рисования на нём возможно использование нескольких контекстов. Самым распространённым является CanvasRenderingContext2D. Обычно именно его имеют в виду, когда говорят об использовании Canvas. Это самый простой и низкоуровневый способ отрисовки в браузере. Однако если разработчик хочет максимально использовать всю мощь графического процессора, то следует рассмотреть возможность использовать WebGL. WebGL API используется с тем же HTML элементом Canvas, однако для отрисовки используется другой контекст рисования - WebGLRenderingContext и используется другой API - WebGL API [4].
Для того, чтобы принять решение об использовании одного из этих двух подходов, необходимо количественно оценить преимущества от использования Canvas по сравнению с DOM-элементами. Реализуем следующий интерфейс с помощью обоих подходов и сравним полученные результаты:
Рис. 1
На данном изображении размером 500×500 пикселей изображены красные квадраты размером 1×1 пиксель с прозрачностью 0,5. Расстояние между каждым квадратом и его соседями - 1 пиксель. Таким образом мы имеем строки и столбцы из 250 квадратов в каждом. Общее число квадратов: 250 × 250 = 62500.
В первом случае рассмотрим реализацию через DOM-элементы. Будем создавать одинаковые div-элементы при помощи функции createElement, задавать им необходимые стили и добавлять в их в существующее DOM дерево при помощи функции appendChild. Всего на странице будет 62500 таких DOM элементов. Запускать страницу мы будем в браузере Chrome, а анализировать результаты быстродействия мы будем при помощи браузерного профайлера. На рисунке ниже изображены результаты работы профайлера Chrome при загрузке страницы.
Рис. 2
Мы видим, что First Paint (FP) произошёл только спустя 1,27 секунды после начала загрузки страницы, а событие DOMContentLoaded (DCL) - спустя 2,46 секунды. При этом стадия выполнения JS-кода заняла 352 мс, стадия Rendering в браузере - 696 мс, а Painting - 1390 мс. Что заняло в общей сложности 2438 мс. Общее потребление памяти всей вкладкой браузера - 485 МБ.
Рис. 3
Рассмотрим теперь отображение с использованием Canvas.
Рис. 4
First Paint (FP) произошёл спустя 94 мс, а DOMContentLoaded (DCL) - спустя 92 мс. При этом стадия выполнения JS-кода заняла 53 мс, стадия Rendering в браузере - 0 мс, а Painting - 1 мс. Что заняло в общей сложности 54 мс. Общее потребление памяти всей вкладкой браузера - 34 МБ.
Рис. 5
Как видно из представленных результатов, при использовании большого числа DOM-элементов экономия памяти и времени работы процессора являются значительными. Результаты работы представлены ниже в сводной таблице:
Таблица
|
DOM |
Canvas API |
First Paint (FP), мс |
1270 |
94 |
DOMContentLoaded (DCL), мс |
2460 |
92 |
Scripting, мс |
352 |
53 |
Rendering, мс |
696 |
0 |
Painting, мс |
1390 |
1 |
Общее время, мс |
2438 |
54 |
Память, МБ |
485 |
34 |
При таких очевидных преимуществах Canvas API зачастую сопряжено с некоторыми сложностями в использовании. Рассмотрим отдельно преимущества и недостатки применения Canvas API [5].
Преимущества:
- Производительность и скорость работы. Как было рассмотрено выше, применения Canvas API позволяет значительно сэкономить на ресурсах клиентского устройства. Тем больше это проявляется при росте числа DOM-элементов и в случае интенсивного использования графики, так как Canvas API позволяет напрямую управлять отдельными пикселями [5].
- Экономия памяти, так как нет необходимости в хранении информации о большом количестве DOM элементов.
- Разработчик может контролировать каждый пиксель в области рисования.
Недостатки:
- Сложность реализации анимаций.
- Управление DOM элементами легче, чем отдельными пикселями, а использование и поддержка кода с использованием Canvas API - сложнее. В случае в DOM элементами часть работы за нас делает браузер.
- Необходимость программистом самостоятельно реализовывать обработку пользовательских событий от визуальных элементов.
- Особенность работы с дисплеями с devicePixelRatio > 1 (например при работе со смартфонами). Программист должны следить за размерами Canvas и иногда это может вести неожиданным артефактам [6].
ЗАКЛЮЧЕНИЕ
В данной статье мы провели сравнительный анализ двух основных подходов к работе с визуальными элементами в веб-разработке: использование DOM элементов и элемента Canvas. Каждый из этих подходов имеет свои уникальные преимущества и недостатки, и правильный выбор зависит от конкретных требований и целей проекта.
Использование DOM элементов предоставляет разработчикам удобство и простоту работы с визуальными элементами, а также интеграцию с CSS и браузерными средствами анимации. Однако это может привести к значительным нагрузкам на ресурсы браузера при работе с большим числом элементов, что снижает производительность. В таких случаях использование элемента Canvas и Canvas API обеспечивают высокую производительность и контроль над каждым пикселем на холсте. Этот подход идеален для создания сложных графических приложений и игр, где скорость отображения данных критически важна. Однако он также требует более глубокого понимания работы с графикой и анимациями, что может усложнить разработку.
Исходя из результатов нашего сравнительного анализа, мы можем утверждать, что выбор между DOM элементами и элементом Canvas зависит от конкретных задач и приоритетов проекта. Важно иметь в виду, что каждый из этих подходов имеет свое место и может быть наиболее подходящим в определенных сценариях веб-разработки. Также оптимальное решение может заключаться в комбинации обоих методов, в зависимости от конкретных компонентов приложения.