Ваши глаза, экран вашего компьютера, ваш браузер и цикл событий JavaScript!

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

Твои глаза

Чтобы человеческий глаз и мозг воспринимали плавное движение, экран должен перерисовываться не менее 24 раз в секунду¹.

В детстве мы рисовали картинки в книжке-книжке² и бегали по ней большим пальцем. Раньше казалось, что картинки движутся.

Лошадь в движении »³ была одной из первых реальных серий, сфотографированных в реальном времени, а не состоящей из серии поставленных фотографий, созданная в США в 1878 году британским фотографом Эдвардом Мейбриджем ⁴.

Если вы зайдете в настройки монитора, то увидите параметр, называемый частотой обновления. Обычно это 60 Гц. Это означает, что монитор перерисовывает ваш экран 60 раз в секунду или 60 кадров в секунду.

Фильмы воспроизводятся со скоростью 24, 25 или 30 кадров в секунду. Постоянство зрения создает в нашем мозгу иллюзию плавности движений.

Экран вашего компьютера

Для компьютерных экранов частота обновления должна быть не менее 60 Гц, иначе мы испытаем головную боль и напряжение глаз. Некоторые экраны имеют 80 Гц и т. Д .; но все, что больше 60 Гц, хорошо.

Давайте подумаем, ладно? 60 Гц означает, что монитору необходимо отрисовать 60 кадров за 1000 миллисекунд. Итак, сколько миллисекунд потребуется монитору, чтобы нарисовать 1 кадр?

Перекрестным умножением получаем…
1 кадр
× 1000 мс
÷ 60 кадров
= ~ 16,667 мс

Таким образом, каждый кадр перерисовывается каждые ~ 16,667 мс, также известный как цикл визуализации.

Ваш браузер

Теперь в каждом цикле рендеринга монитор отправляет сигнал операционной системе на перерисовку экрана. Это достигается с помощью программного обеспечения драйвера дисплея. ОС, в свою очередь, обновляет все приложения на экране. Приложения также уведомляются о событии перерисовки.

Ваш браузер также получает это событие и планирует новое событие перерисовки каждый цикл рендеринга в очереди рендеринга браузера.

Цикл событий JavaScript

Эта перерисовка обрабатывается циклом событий ⁵. Его задача - проверять стек вызовов JavaScript, очередь рендеринга браузера и очередь обратных вызовов браузера и выполнить все функции с очередями с интервалом ~ 16,667 мс.

Вот упрощенный алгоритм в псевдокоде ...

for each render cycle, the event loop does the following…
    if the JavaScript call stack is not empty
        then execute code in the JavaScript call stack
    if the browser’s render queue is not empty
        then execute paint events in the browser’s render queue
    if the browser’s callback queue is not empty
        then execute functions in the browser’s callback queue

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

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

Таким образом, если экран не перекрашивается в течение нескольких циклов рендеринга, пользователи воспринимают то, что на экране «неаккуратно».

Это также влияет на функции, поставленные в очередь обратного вызова браузера. Циклу событий не хватает времени для выполнения прослушивателей событий, поставленных в очередь обратного вызова браузера. Пользователи воспринимают это как «невосприимчивый пользовательский интерфейс».

Вы можете просмотреть и измерить производительность в Инструменты разработчика Chrome - Панель производительности ⁶. Узнайте, как использовать панель Производительность, из статьи Кейси Басков Начало работы с анализом производительности среды выполнения ⁷. Например, вот скриншот измерения производительности анимации гамбургер-меню в моей теме CSS Voxel ⁸ (source: GitHub ⁸).

Заключение

Вот почему мы не должны выполнять операции, которые длятся более ~ 16,667 мс, ни в одной функции прослушивателя событий. Поскольку на каждом кадре так много дел, легко выйти за временной интервал ~ 16,667 мс.

На самом деле мы даже не можем получить весь временной интервал ~ 16,667 мс. Браузер также делится с нами этим временем. Чтобы узнать об этом больше, я поделился ссылками для дальнейшего чтения ниже.

дальнейшее чтение

  1. « Производительность рендеринга от Пол Льюис на сайте Google Developers
  2. Что, черт возьми, за цикл событий? От Филип Робертс на JSConf EU 2014
  3. « Внутреннее устройство виртуальной машины JavaScript, EventLoop, Async и ScopeChains » от Ариндам Пол на JSFoo 2015
  4. Глубокое погружение в libuv от Saul Ibarra Coretge на NodeConf EU 2016

использованная литература

  1. Фильм о взломе: почему 24 кадра в секунду? - Эрик Эскобар
  2. Книжка-раскладушка в Википедии
  3. Лошадь в движении от Идверда Мейбриджа на Wikimedia Commons
  4. « Эдверд Мейбридж » в Википедии
  5. « Модель параллелизма и цикл событий » в веб-документации MDN
  6. Справочник по анализу производительности от Кейси Баскес на сайте Google Developers
  7. Начните с анализа производительности среды выполнения, автор Кейси Баскес на сайте Google Developers
  8. « Воксель - минималистичная тема .» Автор: Rishabh Rao. Источник: github.com/rishabhsrao/voxel