Раскрытие тайны цикла событий

Автор | Сяосюань

Введение 

В этой статье подробно объясняется механизм цикла событий. Из этой статьи вы можете узнать о взаимосвязи между «циклом событий» и «отрисовкой браузера», setTimeout браузера, requestAnimationFrame (RAF), requestIdleCallback (RIC) и другими API в события «Время выполнения» цикла, что вызывает зависание браузера, как измеряются показатели взаимодействия и как улучшить интерактивную производительность веб-сайта.

Полный текст составляет 10 503 слова, предполагаемое время чтения — 27 минут.

01 Предисловие

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

Из этой статьи вы можете узнать о взаимосвязи между «циклом событий» и «рендерингом браузера», браузером setTimeout,

«Время выполнения» API-интерфейсов, таких как requestAnimationFrame (RAF) и requestIdleCallback (RIC) в цикле событий, причины зависаний браузера, способы измерения индикаторов взаимодействия и способы улучшения интерактивной производительности веб-сайта.

Изучив это, вы сможете решать такие вопросы, как почему следует использовать RAF для анимации, когда использовать RIC, следует ли выбирать setTimeout и как избежать длительных задач.

02 Обзор цикла событий

2.1 Зачем нам нужно понимать цикл событий?

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

2.2 Архитектура браузера

Оглядываясь назад на архитектуру браузеров, можно сказать, что современные браузеры являются многопроцессными и многопоточными.

2.2.1 Многопроцессный

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

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

картина

△Мультипроцессная диаграмма браузера

2.2.2 Многопоточность

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

основная тема

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

Основной поток — это основной поток процесса рендеринга, который отвечает за анализ HTML, расчет стилей CSS, выполнение JavaScript, расчет макета, рисование слоев и другие задачи.

картина

△Основной процесс — это граф потока, включенный в процесс рендеринга.

Некоторые задачи должны выполняться в основном потоке. Например, любая операция, которая напрямую требует доступа к DOM (то есть к документу DOM), должна выполняться в основном потоке (поскольку DOM не является потокобезопасным). Сюда будет включена большая часть кода, связанного с пользовательским интерфейсом.

Главный поток может одновременно выполнять только одну задачу .

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

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

картина

03 Конкретный процесс цикла событий

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

картина

△Конкретный процесс возникновения цикла событий

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

Взять задачу (макрозадачу) из очереди задач, выполнить ее и удалить -> Выполнить и очистить все задания (микрозадачи) в очереди -> requestAnimationFrame -- Рендеринг обновления браузера -- requestIdleCallback

3.1 Шаги по обновлению рендеринга

Первые два шага вам знакомы и здесь обсуждаться не будут. Мы сосредоточимся на шагах после «Обновить рендеринг».

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

Если ни одно из этих условий не выполнено и текущий документ не пуст, установите для hasARenderingOpportunity значение true.

2. Если окно изменится, измените его размер.

3. При прокрутке выполните прокрутку.

4. Запросы СМИ.

5. холст.

6. Выполните обратный вызов RAF, передайте параметр обратного вызова DOMHighResTimeStamp и начните выполнение времени обратного вызова.

7. Повторно выполните расчеты, такие как макет, и визуализируйте интерфейс чертежа.

8. Если и очередь задач, и очередь микрозадач пусты, а время рендеринга hasARenderingOpportunity имеет значение false, определяет, выполняет ли алгоритм выполнения функцию обратного вызова requestIdleCallback.

3.2 Последовательность выполнения и рендеринг

Возьмем простой вопрос: определим коды для одновременного создания макрозадач, микрозадач, RIC и RAF и выведем последовательность выполнения.

console.log('开始执行');
console.log('start');
setTimeout(() => {
  console.log('setTimeout');
}, 0);

requestAnimationFrame(() => {
  console.log('requestAnimationFrame');
});
new Promise((resolve, reject) => {
  console.log('Promise');
  resolve('promise resolved');
})

requestIdleCallback(() => {
  console.log('requestIdleCallback');
});

(async function asyncFunction() {
  console.log(await 'asyncFunction');
})();

console.log('执行结束');
// 开始执行
// Promise
// 执行结束
// promise resolved
// asyncFunction
// setTimeout
// requestAnimationFrame
// requestIdleCallback

Вы можете задаться вопросом, почему RAF выполняется до setTimeout(fn, 0). Время выполнения setTimeout(fn, 0) задерживается на 0-4 мс. RAF можно грубо понимать как settimeout(fn, Math.random() * 16.6) Поэтому setTimeout будет иметь приоритет. Однако, если основной поток заполнен другими задачами до выполнения setTimeout и превышает время одного кадра, setTimeout будет выполнен после обратного вызова RAF (см. фрагмент кода ниже для вариантов использования), поэтому время задержки setTimeout не стабильный. Время выполнения RAF стабильное. Все, зарегистрированное в одном кадре, будет выполнено в конце этого кадра и до начала следующего кадра.

  let task = new Array(10000).fill(null).map((_, i) => () => {
    const span = document.createElement("span");
    span.innerText = i;
    console.log("==>task", i);
  });
  task.forEach((i) => i());
  requestAnimationFrame(() => {
    console.log("===>requestAnimationFrame");
  });
  setTimeout(() => {
    console.log("===>setTimeout");
  }, 0);
  //输出:
  // ===>requestAnimationFrame
  // ===>setTimeout

Обратите внимание, что обратный вызов Promise.then может гарантировать точность первого раунда. Если поведение продолжения .then связано с версией браузера, не слишком полагайтесь на последовательность обратных вызовов нескольких .then во время разработки. Это ненадежно. .

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

    const btn = document.querySelector(".btn");
    btn.addEventListener("click", () => {
      box.style.transform = "translateX(400px)";
      box.style.transition = "transform 1s ease-in-out";
      box.style.transform = "translateX(200px)";
    });

Внешний родительский контейнер имеет размер 400 пикселей. Этот код показывает, что поле перемещается от 0 до 200 пикселей, а действие по установке размера поля на 400 пикселей объединяется. Так как реализовать ящик от 400px, можно отложить рендеринг до следующего кадра.

картина

△Демонстрационный эффект

    btn.addEventListener("click", () => {
      box.style.transform = "translateX(400px)";
      requestAnimationFrame(() => {
        requestAnimationFrame(() => {
          box.style.transition = "transform 1s ease-in-out";
          box.style.transform = "translateX(200px)";
        });
      });
    });

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

картина

△Демонстрационный эффект после задержки

04 Очередь задач и время выполнения

Задача JavaScript выполняется перед рендерингом. Если время выполнения JavaScript слишком велико в пределах одного кадра, рендеринг будет заблокирован, что также приведет к потере кадров и задержке . Если время выполнения js здесь слишком велико, это долгая задача , который будет подробно представлен ниже.

Определение длинных задач: если задача занимает более 50 мс , она считается длинной задачей.

Когда мы говорим о длинных задачах, вызывающих зависания страниц, мы обычно имеем в виду задачи в основном потоке (Main Thread). Основной поток — это основной поток процесса рендеринга, который отвечает за анализ HTML, расчет стилей CSS, выполнение JavaScript, расчет макета, рисование слоев и другие задачи. Когда задача (например, функция JavaScript) в основном потоке выполняется слишком долго, она блокирует другие задачи в основном потоке, включая, помимо прочего, обновления пользовательского интерфейса и обработку событий взаимодействия с пользователем, что приводит к зависанию страницы или ее зависанию.

Связь между выполнением JS и рендерингом:

Как выполнение JS, так и задачи Paint происходят в основном потоке. Конкретные операции рисования выполняются потоком синтеза, который не является взаимоисключающим с основным потоком. Однако, если время выполнения JS слишком велико, данные, скомпилированные Paint не будет вовремя отправлен на синтез нить, поэтому на странице есть кадры, которые не отрисовываются, то есть кадры отбрасываются.

картина

картина

△Диаграмма связи между выполнением JS и рендерингом

4.1 Почему бы не использовать setTimeout для анимации?

Сравнение raf и setTimeout:

https://jsfiddle.net/hixuanxuan/mrw6upgs/3/__)

1. Рассинхронизация с частотой обновления дисплея:

Браузеры обычно обновляются со скоростью 60 кадров в секунду, примерно каждые 16,67 миллисекунды. Если вы используете setTimeout для создания анимации и пытаетесь запускать кадр каждые 16,67 миллисекунды, ваш код не будет полностью синхронизирован с частотой обновления браузера, что приведет к потере кадров.

2. Отложенное исполнение:

Параметр времени задержки setTimeout — это только минимальное время задержки, а не гарантированное точное время выполнения. Если основной поток занят другими задачами, обратный вызов setTimeout может быть задержан, что приведет к потере кадров.

3. Слияние таймеров:

Рендеринг браузера имеет возможность рендеринга (возможность рендеринга), то есть браузер будет определять, следует ли выполнять рендеринг на основе текущего контекста просмотра, поскольку принимая во внимание такие факторы, как ограничения частоты обновления оборудования, производительность страницы и наличие у страницы фона. , между задачами макроса Не обязательно сопровождается рисованием в браузере. Если две задачи расположены очень близко, они могут быть объединены в одну задачу рендеринга, и полученные результаты будут неожиданными. Если расстояние задачи велико, оно не сможет справиться с частотой обновления браузера, что приведет к потере кадров.

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

4.2 Время выполнения requestIdleCallback

В основном он выполняется, когда основной поток браузера простаивает. Чтобы обеспечить оперативность, будет рассчитан крайний срок ComputeDeadline, который определит, когда выполнить обратный вызов, зарегистрированный в requestIdleCallback. Вот краткий обзор алгоритма расчета сроков:

1. Установите первоначальный срок:

При инициализации устанавливает время начала последнего периода простоя цикла событий на текущее время.

Установите базовый крайний срок, равный времени начала последнего периода простоя цикла событий плюс 50 миллисекунд (чтобы обеспечить реагирование на новый ввод пользователя). Причина, по которой добавляются эти 50 мс, заключается в том, что браузер заранее подготовлен к некоторым возможным внезапным взаимодействиям с пользователем, таким как ввод текста пользователем. Если заданное время слишком велико и ваша задача блокирует основной поток, на взаимодействие пользователя не будет отвечено. 50 мс гарантирует, что пользователи получат ответ без заметной задержки.

2. Проверьте, есть ли ожидающие рендеры:

Инициализируйте переменную hasPendingRenders значением false.

Перебирайте все окна одного и того же цикла событий, проверяя каждое окно на наличие невыполненных обратных вызовов RAF или возможных обновлений рендеринга. Если да, установите для hasPendingRenders значение true.

3. Настройте крайний срок в зависимости от тайм-аута:

Если RIC передает второй параметр тайм-аут, крайним сроком обновления является тайм-аут. Это заставит браузер выполнить функцию обратного вызова rIC по истечении этого времени, независимо от того, насколько он занят.

4. Учитывайте время рендеринга:

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

Если крайний срок следующего рендеринга раньше установленного в данный момент крайнего срока, крайним сроком обновления является крайний срок следующего рендеринга.

5. Верните окончательный срок:

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

6. Запустите период простоя:

Для каждого окна одного и того же цикла событий выполняется алгоритм «начала периода простоя» с использованием ComputeDeadline в качестве параметра, чтобы определить, когда выполняется обратный вызов, зарегистрированный в requestIdleCallback.

Другими словами, расчет этого timeRemaining() очень динамичен и будет определяться на основе вышеуказанных факторов.

4.3 Как React реализует срез времени и по какой причине не используются RIC и setTimeout?

Причина, по которой RIC не используется, заключается в том, что он плохо работает в некоторых браузерах, таких как Safari.

Условия, которые необходимо выполнить:

1. Приостановите выполнение JS и используйте основной поток для выполнения таких задач, как стилизация, макет, рисование и т. д., давая браузеру возможность обновить страницу.

2. Вы можете продолжать планировать задачи в какой-то момент в будущем и выполнять задачи, которые не были завершены в прошлый раз.

Для React's Time Slice его цель состоит в том, чтобы прервать выполнение текущего js и позволить ему выполнять задачи, связанные с рендерингом. Поэтому требуемый API выполняется после Paint браузера, и браузер не предоставляет API, кроме RIC. Время выполнения RAF приходится на конец одного кадра. В это время создается макрозадача для запуска следующего раунда задач. Задача рендеринга помещается в RAF и выполняется в этом кадре. Если вы используете setTimeout(fn, 0) для создания макрозадачи, и если уровень вложенности таймаута превышает 5 уровней, минимальная задержка составит 4 мс. Для конкретного определения кода обратитесь к определению таймера в Chrome ( https). ://chromium.googlesource .com/chromium/blink/+/master/Source/core/frame/DOMTimer.cpp) , поэтому канал сообщений является предпочтительным, а приоритет выше, чем setTimeout, который может быть выполнен сразу после рендеринг предыдущего кадра завершен, так что можно добиться Эффект прерванного выполнения JS .

4.4. Имитация реализации requestIdecallback

Чтобы имитировать эффект requestIdecallback, определенная очередь задач выполняется после того, как браузер завершает задачу рендеринга. В расширении ее также можно использовать для измерения времени выполнения задачи рендеринга браузера.

API фоновых задач — Веб-API 接口参考 | MDNhttps://developer.mozilla.org/zh-CN/docs/Web/API/Background_Tasks_API)

  // 当到时间了,立即执行的函数
  const performWorkUntilDeadline = () => {
    if (scheduledHostCallback !== null) {
      const currentTime = getCurrentTime();
      // 分配任务的剩余时间,这个可执行时间是根据fps动态算的
      deadline = currentTime + yieldInterval;
      const hasTimeRemaining = true;
      // 调用已计划的回调,并传递剩余时间和当前时间。
      const hasMoreWork = scheduledHostCallback(
          hasTimeRemaining,
          currentTime,
        );
        if (!hasMoreWork) {
          isMessageLoopRunning = false;
          scheduledHostCallback = null;
        } else {
          // If there's more work, schedule the next message event at the end
          // of the preceding one.
          port.postMessage(null);
        }
    } else {
      isMessageLoopRunning = false;
    }
    // 给浏览器一个绘制的机会,并重置需要绘制的标志。
    needsPaint = false;
  };
  
 
  const channel = new MessageChannel();
  const port = channel.port2;
  channel.port1.onmessage = performWorkUntilDeadline;

  requestHostCallback = function(callback) {
    scheduledHostCallback = callback;
    if (!isMessageLoopRunning) {
      isMessageLoopRunning = true;
      port.postMessage(null);
    }
  };

05 Интерактивные показатели эффективности и методы оптимизации

Влияние длинных задач на страницу приводит к неприятным последствиям, таким как «зависание» и «пропускание кадров». Обычно используемые индикаторы для измерения интерактивной производительности включают TTI и FID, которые можно измерить с помощью библиотеки Web-Vital. Ниже приводится подробное введение в показатели.

5.1 Показатели интерактивной производительности

Показатели для измерения интерактивной эффективности в основном сосредоточены на следующих аспектах:

5.1.1 TTI (идеальное время для взаимодействия)

1. Дайте определение интерактивности:

Во-первых, нам нужно уточнить, что такое «интерактив». Страница считается интерактивной, что означает, что основное содержимое страницы загружено, пользователи могут щелкать мышью, вводить данные и выполнять другие интерактивные операции, а страница может быстро реагировать.

2. Мониторинг First Content Paint (FCP) и DOMContentLoaded:

Процесс измерения TTI обычно начинается с мониторинга событий First Content Paint (FCP) и DOMContentLoaded. Эти два события соответственно представляют собой момент, когда браузер начинает рисовать содержимое страницы и загружается структура DOM.

3. Длительный мониторинг задач:

Длинные задачи — это те, выполнение которых занимает более 50 миллисекунд. Длинные задачи часто блокируют основной поток, задерживая интерактивную доступность страницы. Отслеживая длинные задачи, вы можете узнать, когда основной поток становится бездействующим.

4. Найдите интерактивное окно:

Чтобы определить TTI, вам нужно найти окно, в котором основной поток простаивает не менее 5 секунд, и это окно должно быть после первой отрисовки контента (FCP). В течение этого 5-секундного окна простоя не выполняются никакие длительные задачи, а это означает, что пользователь может взаимодействовать со страницей. Как только это окно ожидания будет обнаружено, запишите TTI. Если длинная задача не найдена, TTI такой же, как FCP.

картина

△Диаграмма измерения TTI (с сайта web.dev)

5.1.2 FID (первая входная задержка)

FID, или задержка первого ввода, используется для количественной оценки задержки ответа при первом взаимодействии пользователя при загрузке страницы. Низкий FID указывает на то, что страница быстро реагирует на действия пользователя, а высокий FID указывает на то, что страница реагирует на действия пользователя с задержкой.

1. Мониторинг событий:

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

2. Время обработки события:

Когда событие инициируется, браузер вычисляет время от момента запуска события до момента, когда браузер начинает его обрабатывать. На этот раз ФИД. Он включает в себя время, когда браузер помещает событие в очередь событий, время ожидания в очереди событий и время, когда браузер начинает обрабатывать событие.

3. Обработка событий:

Как только событие начинает обрабатываться, браузер записывает время начала обработки. Если страница сильно занята во время обработки события или имеет другие высокоприоритетные задачи, то обработка события может задерживаться, что приведет к увеличению FID.

5.1.3 INP (взаимодействие со следующим розыгрышем)

INP, или «Взаимодействие с следующей отрисовкой», в основном фокусируется на продолжительности времени от взаимодействия с пользователем (например, щелчка, прокрутки или нажатия клавиши) до ответа страницы, в частности, до визуального обновления определенного элемента на странице.

По сравнению с FID, который фокусируется на первом взаимодействии пользователя после загрузки страницы , INP фокусируется на самой длительной задержке рендеринга всех взаимодействий . Таким образом, INP не только представляет первое впечатление, но также может всесторонне оценить ответ, что делает INP лучше, чем FID при измерении опыта взаимодействия с пользователем. Более надежный.

INP заменит FID в качестве стандартного показателя эффективности в марте 2024 года.

картина

△Время от взаимодействия до рисования

5.2 Как оптимизировать интерактивные показатели эффективности

1. Разделите задачи. Это эффективный способ избежать длительных задач.

  • Используйте анализ производительности для поиска длинных задач

  • Для длинных задач задачи каждого шага разбиваются, выполняются те, которые имеют высокий приоритет, а остальные части прерываются с задержкой выполнения кода.

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

// 通过Promise实现中断后继续执行,setTimeout调用来延迟任务
function yieldToMain () {
  return new Promise(resolve => {
    setTimeout(resolve, 0);
  });
}
    async function saveSettings(tasks) {
      let deadline = performance.now() + 50;

      while (tasks.length > 0) {
        // 判断当前是否有用户交互,isInputPending Chrome87+支持。
        // 可以采用判断Expire Time达到类似效果
        if (
          navigator.scheduling?.isInputPending() ||
          performance.now() >= deadline
        ) {
         // 如果有,退让主线程,等主线程任务完成再回来继续执行。
          await yieldToMain();
          deadline = performance.now() + 50;
          continue;
        }
        const task = tasks.shift();
        task();
      }
    }

    const performLongTask = () => {
       // 创建耗时的任务
      let task = new Array(10000).fill(null).map((_, i) => () => {
        const span = document.createElement("span");
        span.innerText = i;
      });
      saveSettings(task); // 任务切片
    };
    input.addEventListener("input", (e) => {
      input.value = e.target.value;
      performLongTask();
    });

2. Задержка выполнения некритичных модулей. Для модулей с низкой кликабельностью и непрофильных модулей используется динамический импорт и используется перезагрузка, либо загрузка задерживается на определенный период времени, чтобы уменьшить задачи, которые необходимо выполнить основному потоку в первый раз. время.

3. Задержка загрузки контента, который не отображается в области просмотра.

  • Ленивая загрузка изображений.

  • Установите для тега img режим отложенной загрузки, чтобы задержать загрузку ресурса до тех пор, пока ресурс не достигнет расчетного расстояния от области просмотра. Chrome77+ поддерживает это.

  • Используйте IntersectionObserver, чтобы отслеживать, находится ли изображение в видимой области, а затем визуализировать его. Рекомендуется использовать такие библиотеки, как lazy-load-image-comComponent ( https://www.npmjs.com/package/react-lazy-load-image-comComponent) .

  • Уменьшите рендеринг большого количества DOM. Используйте видимость контента для задержки рендеринга элементов за кадром, Chrome85+ поддерживает это.

4. Гибкая стратегия кэширования.

  • Используйте service-worker для совместного использования ресурсов между сайтами.

В дополнение к ресурсам, которые можно комбинировать с сильным кэшированием + согласованным кэшированием, Service-Worker можно использовать для реализации более гибкой стратегии кэширования. Например, сайт a и сайт b имеют один и тот же источник, но методы рендеринга стека технологий совершенно разные.Как предварительно выбрать ресурсы b при доступе к a. Зарегистрируйте Service-Worker, когда сайт A простаивает.При доступе к сайту B кэш можно прочитать из кэша, чтобы повысить скорость загрузки. sw не только хорошо работает при кэшировании, но также может помочь нам реализовать автономные приложения и вручную добавить кеш к файлам, которые не могут быть сильно кэшированы браузерами (разные браузеры имеют разные ограничения на размер файлов, которые могут быть сильно кэшированы).

картина

△Используйте SW для предварительной загрузки межсайтовых ресурсов.

06 Резюме

1. Браузеры являются многопроцессными и многопоточными.Обычно основной поток относится к основному потоку процесса рендеринга.

2. Основной поток может одновременно запускать только одну задачу. Отрисовка браузера и основной поток не являются взаимоисключающими, но длинные задачи будут вызывать задержки при входе в синтез, и даже если синтез не произойдет в этом кадре, кадр будет быть отброшено.

3. В конце каждого цикла событий рендеринг может не произойти. Время выполнения setTimeout нестабильно.

4. Тайминг выполнения RAF стабилен в конце текущего кадра и перед началом следующего кадра, что очень удобно для анимации.

5. Время выполнения RIC нестабильно. ComputeDeadline рассчитывается с учетом множества факторов, но крайний срок выполнения управления тайм-аутом может быть пропущен.

6. Используйте TTI и FID (INP) для измерения интерактивной производительности страницы.

7. Улучшите интерактивную производительность веб-сайта за счет разделения длинных задач, задержки выполнения некритических модулей, задержки загрузки изображений в невидимых областях, уменьшения рендеринга страниц и настройки гибких стратегий кэширования.

--КОНЕЦ--

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

[1] Живой стенд HTML — модель обработки цикла evnet:

https://html.spec.whatwg.org/multipage/webappapis.html#event-loop-processing-model

Рекомендуемое чтение:

Реконструкция сервиса отображения поиска Baidu: прогресс и оптимизация

Практика оптимизации пакета iOS приложения Baidu размером 50 МБ (7) Оптимизация компилятора

Система хранения таблиц HTAP для поиска контента Baidu

Как в эпоху больших моделей выглядит платформа разработчиков Baidu, согласно которой «каждый может создавать ИИ»?

Сотни тысяч запросов в секунду, гарантия стабильности Baidu для поиска горячих событий

Тан Сяоу, основатель SenseTime, скончался в возрасте 55 лет. В 2023 году PHP находился в застое . Система Hongmeng вот-вот станет независимой, и многие университеты создали «классы Hongmeng». Версия Quark Browser для ПК начала внутреннее тестирование. ByteDance был «запрещен» OpenAI. Стартап-компания Чжихуэйцзюня была рефинансирована на сумму более 600 миллионов юаней, а предварительная оценка составила 3,5 миллиарда юаней. Помощники по написанию кода на основе искусственного интеллекта настолько популярны, что они даже не могут конкурировать в программировании. языковые рейтинги Mate 60 Pro модем 5G и радиочастотная технология далеко впереди No Star, No Fix MariaDB отделяется от SkySQL и становится независимой компанией
{{o.name}}
{{м.имя}}

рекомендация

отmy.oschina.net/u/4939618/blog/10322486
рекомендация