Scroll Listener VS Intersection Observer. Сравнение производительности
Interection Observer API даёт возможность вызвать коллбэк, когда пересекаются DOM-элементы. Можем ли мы им заменить обработчики scroll cобытий? Что менее затратно по производительности? В этой статье мы попытаемся ответить на это.
Подготовка
Для того, чтобы сравнить эти 2 подхода, я создал абсолютно простое SPA приложение: страница с 4 секциями текста. Когда вы скроллите от одной секции к другой, hash страницы обновляется в зависимости от того, какую секцию вы просматриваете сейчас. Очень просто, да? Если не понятно, можете перейти по ссылке.

Я создал 2 версии приложения: одну со Scroll Listener, другую с Intersection Observer. Во второй код довольно простой, без никаких хаков, хитростей для производительности. Для scroll-обработчика, я создал 3 разные версии.
Без кэширования offset, без throttle.
Эта версия просто добавляет нужный scroll-обработчик без кэширования никаких значений, которые могут оставаться такими же(а именно offset, отступ от каждой секции) или добавления throttle на обработчик.С кэшированием, но без throttle
В этой версии мы кэшируем offset, расстояние до секций, которое не изменяется, пока не изменится ширина сайта. Но при этом не добавляем throttle на слушатель scroll.С кэшированием и throttle
Эта версия такая же, только с добавлением throttle 300мс на коллбэк Scroll Listener.
Измерения
Сравнения были сделаны с использованием вкладки performance в Chrome Devtools. Чтобы точно воспроизвести компьютер со средней мощностью, я добавил 4x замедление на CPU. Затем я замерил 4 версии на производительность, пока скроллил от самого верха страницы до самого низа, не останавливаясь. Результаты следующие:




Краткое объяснение:
Желтый по сути означает вычислительную нагрузку. Чем больше жёлтого, тем больше работы для главного потока
Зелёный над жёлтым — это FPS. Чем выше и ровнее, тем приятнее для пользователя.
Маленькие красные точки над зелёным могут означать множество вещей (в общем —задержки для пользователя). В нашем случае они означают, что время коллбэка вышло за пределы одного цикла Event Loop. Чем их меньше, тем лучше.
Если мы суммируем всё желтое время и разделим на общее время, то получим процент времени, потраченный на выполнения скрипта во время основного потока:
Процент от общего времени обработки скрипта:
Scroll Listener — без кэширования и throttle: 48.9%
Scroll Listener — с кэшированием, без throttle: 43.5%
Scroll Listener — с кэшированием и throttle: 28.9%
Intersection Observer: 23.3%
Пара интересных замечаний: Intersection Observer сравним только с оптимизированным Scroll Listener. Это интересно, так как мы не добавили никакие оптимизации на сам observer. Если мы замедлим CPU еще больше до 6x, симулируя старые мобильные телефоны, и сделаем эти же тесты заново, то результаты получатся еще более ясными:


Процент от общего времени обработки скрипта:
Scroll Listener — с кэшированием и throttle: 63.0%
Intersection Observer: 37.6%
Это значит, что когда мы используем Intersection Observer, главный поток на 43% более свободен, чтобы отвечать на действия пользователя (на очень медленных устройствах)
Заключение
Что мы попытались тут сделать, это сравнить производительность двух решений одной проблемы. Конечно, есть случаи, когда Scroll Listener будет более подходящим выбором, но для основных задач, таких как смена хэша урла, изменение каких-то стилей по скроллу или sticky-поведение на определённых точках, Observer API работает лучше и является более предпочтительным по производительности.
Код: https://codesandbox.io/s/x7n0kmxjvo?fontsize=14
Оригинал статьи: https://itnext.io/1v1-scroll-listener-vs-intersection-observers-469a26ab9eb6
Спасибо за чтение!
Итог: если есть возможность обойтись Intersection Observer — используем его. В противном случае возвращаемся к Scroll Listener.