Почему setTimeout имеет минимальную задержку 4 мс?

дизайн
Почему setTimeout имеет минимальную задержку 4 мс?

Why's THE Design – это серия статей о программных решениях в компьютерной сфере (предпочтительно в области фронтенда). В этой серии с разных точек зрения будут обсуждаться преимущества и недостатки этого дизайна, а также его влияние на конкретные реализации. Вдохновленный «Почему это спроектировано таким образом» Дрейвнесса

текст

В кругу передовых технологий, дляsetTimeoutЧасто делается вывод:setTimeoutМинимальная задержка установки составляет 4 мс". Согласно подходу «каким-то образом», прежде чем ответить на вопрос, вы должны «увидеть, так ли это» и «увидеть, правильно ли это или почему».

Сначала рассмотрим первый вопрос,«Существует ли конкретная спецификация, определяющая 4 мс, или это просто установленный факт отраслевой практики?»

Знакомый с интерфейсом знаю,setTimeoutОн не поддерживается ECMAScript, а предоставляется хост-средой, а конкретные спецификации поддерживаются whatwg (насчет того, почему ECMAScript напрямую не предоставляет функцию setTimeout, в esdiscuss в 2011 году было много дискуссий, и участники включая Брендана Эйха, Кайла Симпсона и других пожилых людей, которые будут кратко упомянуты позже или в другой статье). Вернемся к стандарту html, в8.6 Timers-2020/6/23среда дляsetTimeout()а такжеsetInterval()Подробное описание смотрим на одну из строк 10-13:

  1. If timeout is less than 0, then set timeout to 0.
  2. If nesting level is greater than 5, and timeout is less than 4, then set timeout to 4.
  3. Increment nesting level by one.
  4. Let task's timer nesting level be nesting level.

Из приведенной выше спецификации видно, что:

  1. Если установленоtimeoutменьше 0, установить на 0
  2. Если уровень вложенности превышает 5 уровней и время ожидания меньше 4 мс, установите время ожидания на 4 мс.

На данный момент мы, похоже, нашли источник 4 мс и более точное определение минимальной задержки для setTimeout —«4 мс будет установлено только в том случае, если уровень вложенности превышает 5 уровней одновременно, а время ожидания меньше 4 мс»

Некоторые люди могут задаться вопросом: "Каков уровень вложенности таймера?" (мне тоже любопытно), посмотрите на следующий код (как реализовать уровень вложенности таймера и минимальную задержку в конкретном исходном коде браузера, что будет объяснено позже через исходный код хрома):

setTimeout(() => {
  setTimeout(() => {
    setTimeout(() => {
      setTimeout(() => {
        setTimeout(() => {
          
        }, 0)        
      }, 0)      
    }, 0)
  }, 0)
},0)

До сих пор, кажется, в состоянии объяснитьsetTimeoutО конструкции минимальной задержки. Но, как часто говорят на станции Б,"Вы видели только второй этаж и думали, что я на первом этаже, а на самом деле я дошел до пятого этажа".

Когда я увидел этот вопрос, поднятый группой друзей, моей первой мыслью, помимо поиска источника спецификации, были две другие проблемы:

  1. Реализовали ли их основные производители браузеров в соответствии со спецификациями, и если нет, то почему?
  2. Как именно определяется число 4мс?

Как я часто думал,«За, казалось бы, простым результатом дизайна должен быть корень, который может исходить из болевых точек, фона и ограничений в то время. Нам нужно не только понимать дизайн, но, что более важно, понимать вещи, стоящие за дизайном, такие как главный технический вопрос: как производители играют в игры за кулисами и находят компромиссы»

Давайте сначала посмотрим на основные популярные браузеры.setTimeoutЗадержка вывода различных крайних случаев (следует отметить, что увеличение задержки setTimeout из-за задержки отдельного цикла обработки событий здесь не рассматривается, и она упрощена до самой примитивной ситуации. Конкретно ситуация, когда время выполнения в одиночном цикле слишком длинное не считается, если предположить, что время выполнения одиночного цикла велико (меньше уровня мс):

  1. Chrome 83.0.4103.106 и Safari/край

  1. Firefox 65.0.1 и IE 11

Глядя на рисунок выше, мы найдем, что дляsetTimeoutустановить задержку0msа также1ms, основные производители браузеров приняли две стратегии. И какова конкретная стратегия?После того, как мы вводим исходный код браузера, чтобы найти его (здесь мы показываем только исходный код хрома, другие webkit или Firefox могут загрузить и просмотреть его самостоятельно), в каталоге blink хрома есть вызываемые файлы DOMTimer .cpp,онлайн-адрес, где также устанавливается задержка таймера:

static const int maxIntervalForUserGestureForwarding = 1000; // One second matches Gecko.
static const int maxTimerNestingLevel = 5;
static const double oneMillisecond = 0.001;
// Chromium uses a minimum timer interval of 4ms. We'd like to go
// lower; however, there are poorly coded websites out there which do
// create CPU-spinning loops.  Using 4ms prevents the CPU from
// spinning too busily and provides a balance between CPU spinning and
// the smallest possible interval timer.
static const double minimumInterval = 0.004;

double intervalMilliseconds = std::max(oneMillisecond, interval * oneMillisecond);
if (intervalMilliseconds < minimumInterval && m_nestingLevel >= maxTimerNestingLevel)
    intervalMilliseconds = minimumInterval;

Логика кода очень понятна, установлены три константы:

  1. maxTimerNestingLevel = 5. То есть уровень вложенности, упомянутый в стандарте HTML
  2. minimumInterval = 0.004. То есть минимальная задержка, указанная в стандарте HTML.

Во втором фрагменте кода мы увидим, что сначала время задержки и1msпринять максимальное значение между ними. Другими словами, в случае, когда уровень вложенности не удовлетворяется, минимальное время задержки устанавливается равным1ms. Это также объясняет, почему тестирование в ChromesetTimeoutрезультат выше.

В комментарии хрома объясняется, почему вы хотите установитьminimumInterval = 4ms. Чтобы поставить его просто, команда Chromium хочет установить более низкую задержку (на самом деле, они ожидают, что уровень суб-миллисекундии), но из-за того, что некоторые веб-сайты (такие как сайт New York Times)setTimeoutПлохое использование этого таймера и слишком низкая задержка приведут к вращению ЦП (позже мы объясним, что такое вращение ЦП), поэтому хром провел несколько тестов производительности и выбрал4msкак его минимальный интервал.

До сих пор это объяснялось с точки зрения производителя браузера и стандартной спецификации HTML.4msисточник и его более точное определение. Но возникнет новое любопытство, будь то настройки, сделанные сначала стандартом HTML, или настройки, сделанные производителями браузеров, такими как Chromium. Значение понимания последовательности заключается в том, чтобы понять историю, стоящую за ней, то, как нормы и производители способствуют и уравновешивают друг друга.

Давайте сначала перейдем к уровню операционной системы, разрешение таймера по умолчанию для Windows равно10-15.6ms(Здесь вы можете понять гранулярность таймера), что означает, что таймер браузера изначально зависит от разрешения таймера на уровне операционной системы. изменить наsetTimeoutСреди них установленная минимальная задержка будет не менее10ms. Однако, с точки зрения производительности процессора, скорость процессора была увеличена с 500 Гц в 1995 году до более чем 3 ГГц (она была достигнута в 2010 году), в то время как таймер Windows по умолчанию не изменился, сохранив исходный10-15.6ms(Здесь вы увидите, как производители браузеров и производители операционных систем думают с разных точек зрения). Поставщик браузера (chrome) считает, что таймер по умолчанию влияет на представление веб-страницы (10-15.6msслишком долго). Для браузера внутри, если часы тикают очень долго, это означает, что браузер будет спать в течение длительного времени, что приводит к снижению производительности браузера определенным образом.

Приведенное выше объяснение говорит нам об установленном факте, что реализация таймера всех браузеров под окном изначально зависит от таймера операционной системы, т.е.10-15.6ms. Фактические результаты теста можно увидеть из теста визуальной сортировки Эрика Кея и Джона Ресина (автора знаменитого JQuery, вы обнаружите, что у большого парня есть собственное понимание базовых слоев), чтобы увидеть,В частности, статья Джона Ресина 2008 г..

хром для10-15.6msТаймер очень обеспокоен. Мы знаем, что Chrome разработан как высокопроизводительный современный браузер, особенно разрешение таймера, которое надеется достичь субмиллиметрового уровня (менее 1 мс). Поэтому команда Chrome надеется изменить зависимость браузера от таймера операционной системы и принимает различные решения для систем Windows и Linux/Unix для достижения своей цели. В Linux/unix есть специальный API для изменения разрешения таймера по умолчанию в системе, но это немного проблематично под Windows Наконец, команда chromium выбрала тот же API, что и Flash и Quicktime, чтобы заменить разрешение таймера по умолчанию в системе.

После изменения разрешения таймера ОС по умолчанию производительность Chrome значительно улучшилась. В бета-версии Chrome 1.0 для разрешения таймера установлено значение1ms(Уже близко к ожиданиям своей команды). Некоторые люди могут задаться вопросом, поскольку стремление к низкой задержке, почему бы не установить его прямо на0msШерстяная ткань?

Причина этого в том, что если браузер позволяет0ms, приведет к перегрузке движка JavaScript, а это означает, что если архитектура браузера является однопроцессной, веб-сайт может легко перестать отвечать на запросы. Поскольку сам браузер тоже построен на цикле событий, если медленный движок JavaScript будет постоянно пробуждать систему через таймер 0 мс, то цикл событий будет заблокирован. Так что же происходит с пользователем в это время? Когда вы одновременно сталкиваетесь с вращением процессора и практически зависанием браузера, мысли об этом приводят людей в ступор. Если браузер часто заставляет пользователей испытывать такую ​​ситуацию, абсолютно никто не хочет его использовать, ведь мало кто хочет, чтобы его ругали. Вот почему бета-версия Chrome 1.0 настроена на1ms.

Кажется, что результаты очень хорошие, но потом у некоторых команд есть отчеты об ошибках (конкретно, две, одна из которых — упомянутая ранее ошибка веб-сайта New York Times, а другая — ненормальное энергопотребление хрома, обнаруженное командой Intel). Было обнаружено, что таймер вызывает вращение ЦП, и следствием этого является то, что компьютер не может перейти в спящий режим (режим низкого энергопотребления), что означает очень быстрое энергопотребление. Поэтому команде хрома приходилось решать практические задачи (к тому же, поскольку доля рынка хрома в то время была не такой большой, как сейчас, она не смела быть слишком большой). В то время в планы команды chrome входило установить множество ограничений на таймер. Позже, после некоторых экспериментов команды chrome, было обнаружено, что1msулучшить до4ms, похоже, на большинстве машин нет проблем с вращением процессора и чрезмерным энергопотреблением. С этим компромиссом достигается цель команды chrome, более точный таймер, а также отсутствие проблем.

В качестве отступления, на самом деле вначале команда chrome общалась с командой windows, надеясь, что windows сможет предоставить функцию динамической настройки интервала тиков аппаратных часов в соответствии с потребностями приложений верхнего уровня, но результат общения не так ладно. Это можно понять из презентации Microsoft, которая не хотела вносить такое изменение.В презентации они надеялись, что будущая ОС сможет обеспечить более низкую скорость пробуждения (100 мс) для приложений верхнего уровня, чтобы уменьшить много поведение Неправильная процедура. То есть ожидания команды Chrome и ожидания команды Windows противоречат друг другу. На этом этапе мы поймем, что разные команды по-разному относятся к одному и тому же.

После того, как команда Chrome настроила таймер (производительность значительно улучшилась), другие основные браузеры, такие как (Safari, Opera, Firefox, IE), приняли4msУстановка, и разные браузеры будут выполнять таймер дросселирования в разных условиях (то есть причина, по которой мы изначально проверили разные браузеры с разными результатами). Только тогда установил стандартные установки HTML соответствующих спецификаций.

На самом деле разрешение таймера — это не та тема, которая часто обсуждается (потому что требует много базовых знаний и смещено в сторону дна), но на самом деле разрешение таймера постоянно развивается.

Как упомянул Николас С. Закас в одной из своих статей: «Мы приближаемся к тому моменту, когда можно будет управлять браузером с точностью до миллисекунды. разрешение снова падает. До тех пор имейте в виду 4 мс, но помните, что вы все равно не всегда получите это ».

Суммировать

Здесь можно понять, что,setTimeoutиз4msкак устроено. Мы можем иметь более точное определение минимальной задержки для этого метода.

  1. Минимальная временная задержка в разных браузерах несовместима, например, самая низкая задержка в Chrome составляет1ms. А если уровней вложенности таймеров много, то минимальная задержка равна4ms. Порог определенного уровня вложенности не согласуется с разными браузерами.В стандарте HTML это>5, в хроме это>=5.

Кроме того, мы также понимаем две проблемы, упомянутые ранее:

  1. Реализовали ли их основные производители браузеров в соответствии со спецификациями, и если нет, то почему?
  2. Как именно определяется число 4мс?

Основные производители браузеров не полностью реализуют спецификации, потому что у каждого из них есть свои тесты, а затем разные производители браузеров сделали разные настройки. Кроме того, стандарт HTML предоставляет соответствующие гибкие изменения для таких переменных, которые не оказывают существенного влияния. мы также понимаем4msПредыстория и различные соображения производителей браузеров и производителей операционных систем, стоящие за ними, их соответствующие решения и компромиссы.


Я BY, интересный человек, в будущем будет больше оригинальных статей.

Эта статья следует лицензии MIT, пожалуйста, свяжитесь с автором для перепечатки.

Если вы заинтересованы, вы можете подписаться на официальный аккаунт (принцип Baixue) или репозиторий Star GitHub.