веб-разработчик, Санкт-Петербургский политехнический университет Петра Великого, РФ, г. Санкт-Петербург
ИССЛЕДОВАНИЕ ВЛИЯНИЯ LAYOUT THRASHING НА ПРОИЗВОДИТЕЛЬНОСТЬ ВЕБ-ПРИЛОЖЕНИЙ И МЕТОДЫ ПО ЕГО ОПТИМИЗАЦИИ
АННОТАЦИЯ
Данная научная статья представляет собой исследование и анализ явления “Layout thrashing” и его влияния на производительность веб-приложений. Подробно рассматриваются механизмы чтения и записи данных в DOM, которые могут привести к последовательному вызову Forced reflow и Layout thrashing, замедляя работу приложений и ухудшая производительность.
В данной статье представлены ключевые аспекты:
- Понимание проблемы: обсуждается важность понимания и распознавания проявлений Layout thrashing в веб-приложениях и описывается то, как это может сказаться на производительности.
- Методы оптимизации: представлены разнообразные методы оптимизации, включая использование CSS-решений, разделение операций чтения и записи, использование альтернативных API и другие стратегии, направленных на снижение воздействия Layout thrashing.
- Практическое применение: продемонстрирована эффективность оптимизации Layout thrashing на практике и приведены количественные данные, сравнивающие различные методы оптимизации в сценариях веб-разработки.
В заключение, данная статья призывает веб-разработчиков уделять должное внимание оптимизации операций с DOM и Layout thrashing, чтобы обеспечить максимальную производительность и качество кода в современных веб-приложениях.
ABSTRACT
This scientific article is a study and analysis of the phenomenon of “Layout thrashing” and its impact on the performance of web applications. It goes into detail about the mechanisms for reading and writing data into the DOM, which can lead to sequential Forced reflow and Layout thrashing, slowing down applications and degrading performance.
This article presents these key aspects:
- Understanding the problem: It discusses the importance of understanding and recognizing Layout thrashing in web applications and describes how it can impact performance.
- Optimization techniques: A variety of optimization techniques are presented, including the use of CSS solutions, separation of read and write operations, the use of alternative APIs, and other strategies aimed at reducing the impact of Layout thrashing.
- Practical application: The effectiveness of Layout thrashing optimization in practice is demonstrated and quantitative data is provided comparing various optimization methods in web development scenarios.
In conclusion, this article encourages web developers to pay due attention to optimizing DOM operations and Layout thrashing to ensure maximum performance and code quality in modern web applications.
Ключевые слова: Layout thrashing, Forced reflow, производительность, DOM, оптимизация, веб-разработка, профайлер, браузер.
Keywords: Layout thrashing, Forced reflow, performance, DOM, optimization, web development, profiler, browser.
Введение
В современной веб-разработке одной из проблем, влияющих на производительность веб-приложений, является явление, называемое "Layout thrashing" (последовательный вызов Forced reflow). Этот процесс связан с операциями чтения и записи данных в DOM-элементы браузера из JavaScript-кода и может существенно замедлять работу веб-приложений.
В данной научной статье мы глубоко исследуем Layout thrashing и его влияние на производительность веб-приложений. Также мы рассмотрим различные сценарии, в которых он может происходить.
Мы также представим различные методы оптимизации, направленные на снижение негативных эффектов Layout thrashing. Эти методы включают в себя использование CSS-решений, разделение операций чтения и записи, выбор более эффективных альтернативных API и другие приемы.
Важно отметить, что Layout thrashing может существенно замедлить работу веб-приложений и его оптимизация играет важную роль в обеспечении высокой производительности при работе с DOM-элементами. Мы также представим количественные данные, сравнивающие различные методы оптимизации и их влияние на скорость выполнения кода.
Изучив и оптимизировав поведение Layout thrashing, разработчики смогут повысить производительность и обеспечить более плавное и отзывчивое поведение своих веб-приложений, что является одним из ключевых аспектов в современной веб-разработке.
Основная часть
Операции с DOM-деревом в JavaScript-коде выполняются значительное время в браузерах. Именно это и стало причиной появления такой концепции, как Virtual DOM, которая например реализована в одной из самых популярных frontend библиотеках - React. При использовании этого подхода минимизируется количество обращений к DOM-элементам и увеличивается скорость работы веб-приложения [1].
Рассмотрим процесс обращения к DOM-элементам в браузере из JavaScript кода более подробно.
- Чтение
Чтение данных для быстродействия происходит из браузерного кэша, поэтому это происходит относительно быстро. Кэш пересчитывается на этапе расчёта layout. Это может происходить в нескольких случаях - после выполнения JavaScript кода и перед стадией Paint или же перед чтением определённых свойств с размерами, позиционированием и другими стилями из JavaScript, например свойство clientHeight. На рисунке 1 мы видим процесс выполнения единственной операции считывания значения свойства, значение которого берётся из браузерного кэша. После выполнения JavaScript кода происходит вычисление стилей и layout, а затем стадии Paint и Compositing [2].
Рисунок 1. Чтение из DOM
- Чтение → Запись
При наличии в JavaScript коде операции записи сразу после операции чтения, происходит инвалидация браузерного кэша. Однако так как это значение больше нигде не считывается в коде, то пересчёта кэша сразу не происходит. Это происходит чуть позже, во время стадии layout, которая следует за выполнением JavaScript кода. Подобное поведение описано на рисунке 2.
Рисунок 2. Чтение и запись в DOM
- Запись → Чтение
Если поменять местами операции чтения и записи, то сначала при записи кэш станет невалидным и будет пересчитан сразу перед последующей операцией чтения, для того, чтобы прочитать актуальные значения. Такой принудительный пересчёт кэша (и стадии layout) называется forced reflow. Подобное поведение показано на рисунке 3. После исполнения JavaScript кода операция пересчёта layout проводиться не будет, так как браузерный кэш и так находится в валидном состоянии.
Рисунок 3. Запись и чтение из DOM
- Запись → Чтение → Запись → Чтение
При наличии более чем одного цикла записи/чтения, происходит следующее: при записи кэш становится невалидным и перед чтением происходит ресурсозатратный пересчёт кэша. И далее операция повторяется столько раз, сколько у есть циклов записи/чтения. И во время каждого цикла кэш становится невалидным. Такое поведение изображено на рисунке 4 и называется layout thrashing - последовательный вызов forced reflow для одних и тех же DOM-элементов. Такое поведение значительно снижает быстродействие всего приложения и считается нежелательным [3].
Рисунок 4. Два цикла записи и чтения из DOM
Именно такое поведение, при котором браузерный кэш становится невалидным и браузер вынужден пересчитывать его, называется forced reflow. Обычно это происходит при работе с DOM элементами в цикле, при сменяющих друг друга операциях записи и чтения.
Пересчёт layout будет происходить при обращении к свойствам, которые характеризуют размеры и положение элемента на странице (например clientHeight, offsetWidth, …), вызов функций, которые возвращают геометрические характеристики элемента (getBoundingClientRect и getClientRect), сущности, относящиеся к прокрутке на странице (например scrollBy, scrollHeight), innerText, getComputedStyle, а также некоторые другие свойства или функции [4].
Тестовое приложение
Рассмотрим тестовое React приложение, в котором будем рендерить большое число одинаковых React компонентов со следующим кодом:
ref.current.style.backgroundColor = color;
ref.current.style.width = `${contentSize}px`;
ref.current.style.height = `${contentSize}px`;
const width = ref.current.clientWidth;
В первых трёх строчках мы устанавливаем стили для элемента, а в четвёртой строчке производится чтение длины элемента. Исследуем в профайлере браузера Chrome поведение такого кода при повторном рендеринге 1200 таких элементов (рисунок 5).
Рисунок 5. Изображение Layout thrashing в профайлере Chrome
На рисунке 5 мы видим большое количество фиолетовых элементов, которые означают пересчёт стилей и layout DOM-элементов. Увеличенное изображение этих фиолетовых элементов мы видим на рисунке 6. На рисунке видно, что профайлер указывает нам на проблемы в быстродействии, а также на каких стадиях в браузере это произошло. При выделении проблемного участка есть возможность даже узнать о конкретной строчке JavaScript кода, которая вызвала Forced reflow.
Рисунок 6. Информация о Forced reflow из профайлера Chrome
Для решения подобных проблем, связанным с Layout thrashing предлагается использовать один из следующих методов [5]:
- CSS решение.
Самым лучшим решением проблемы Layout thrashing является CSS решение. Если, исходя из задачи, удастся удалить вызвавший reflow участок кода и заменить его выставлением необходимых CSS стилей, то это будет являться наилучшим и самым оптимальным решением.
- Разделение чтения и записи.
Необходимо разделить операции чтения и записи в две разные задачи в JavaScript коде. Для этого можно использовать функцию setTimeout или же, что более оптимально - requestAnimationFrame. Ниже приведён пример такого кода:
ref.current.style.backgroundColor = color;
ref.current.style.width = `${contentSize}px`;
ref.current.style.height = `${contentSize}px`;
requestAnimationFrame(() => {
const width = ref.current.clientWidth;
});
- Менее затратный Layout thrashing.
Если первые два способа не помогли, то можно использовать менее затраты по ресурсам Layout thrashing. Например, менять такое CSS свойство, изменение которого будет вести к пересчёту layout, но не к пересчёту стилей.
- Альтернативные API.
Также стоит отметить, что для решения проблемы Layout thrashing можно воспользоваться такими JavaScript API, как ResizeObserver, IntersectionObserver или window.matchMedia.
Стоит отдельно отметить, что большинство проблем с Layout thrashing решаются первыми двумя способами.
В таблице 1 приведено количественное сравнение времени выполнения оригинального кода без оптимизаций и оптимизациями с использованием CSS решения и решения с разделением операций чтения и записи (используя requestAnimationFrame).
Таблица 1.
Сравнение времени выполнения оригинального кода без оптимизаций и оптимизациями
Название решения |
Время выполнения, с |
Без оптимизаций |
2,36 |
CSS решение |
0,148 |
Использование requestAnimationFrame |
0,183 |
Отдельно стоит отметить, что одним из самых эффективных инструментов для оптимизации быстродействия и поиска проблемных мест в коде является браузерный профайлер. С его помощью легко можно узнать на что тратится процессоре время и на каких стадиях в браузере. Особенно это актуально для работы с Layout thrashing. Например профайлер браузера Chrome прямо указывает на такие проблемы в веб-приложении и конкретные места в коде [6].
Заключение
В заключение стоит отметить важность понимания и оптимизации такого явления, известного как "Layout thrashing" в веб-разработке. Этот процесс, связанный с пересчетом стилей и layout DOM-элементов при операциях чтения и записи данных в DOM, может серьезно влиять на производительность веб-приложений. Проведённые исследования позволили выделить несколько ключевых моментов:
- Понимание последствий. Было доказано, что Layout thrashing может стать серьезным замедлением веб-приложений и вызвать неудовлетворение пользователей. Профилирование кода с использованием браузерных инструментов может помочь выявить проблемные участки.
- Методы оптимизации. Были представлены различные методы оптимизации, такие как использование CSS решений, разделение операций чтения и записи, выбор более эффективных альтернативных API и другие приемы. Эти методы помогают уменьшить влияние Layout thrashing и улучшить производительность веб-приложений.
- Практическое применение. Было продемонстрировано как оптимизация Layout thrashing может значительно ускорить выполнение кода в веб-приложениях. Эффективное управление операциями чтения и записи данных в DOM может привести к значительному улучшению производительности.
В завершение, стоит отдельно отметить, что при веб-разработке необходимо принимать во внимание значимость Layout thrashing и проактивно применять методы оптимизации, представленные в этой статье. Это поможет создавать быстрые, отзывчивые и оптимизированные веб-приложения, что является неотъемлемой частью современной веб-разработки.
Список литературы
- К. Ю. Бетеев, Г. В. Муратова, Концепция Virtual Dom в библиотеке React.js // Инженерный вестник Дона. – 2022. – № 3(87). – С. 170-180. – EDN LHOOOS.
- Paul Irish, Tali Garsiel, How browsers work [Электронный ресурс] - URL: https://web.dev/articles/howbrowserswork (дата обращения: 20.10.2023)
- Jeremy Wagner, Paul Lewis, Avoid large, complex layouts and layout thrashing [Электронный ресурс] - URL: https://web.dev/articles/avoid-large-complex-layouts-and-layout-thrashing (дата обращения: 20.10.2023)
- Paul Irish, What forces layout / reflow [Электронный ресурс] - URL: https://gist.github.com/paulirish/5d52fb081b3570c81e3a (дата обращения: 20.10.2023)
- Joe Liccini, Layout Thrashing and Forced Reflows [Электронный ресурс] - URL: https://webperf.tips/tip/layout-thrashing (дата обращения: 20.10.2023)
- Кузьмичев И. П., Профилирование и оптимизация WEB приложений // Молодой исследователь: вызовы и перспективы: Сборник статей по материалам CCCIV международной научно-практической конференции, Москва, 17 апреля 2023 года. Том 15 (304). – Москва: Общество с ограниченной ответственностью "Интернаука", 2023. – С. 197-200. – EDN GBGQLC.