В Інтернеті швидкість – це все. Швидкість вашого веб-переглядача, час, потрібний для появи веб-програми, і те, наскільки швидко ця програма обробляє взаємодії користувача, усе це безпосередньо впливає на ваш досвід як веб-користувача.
У корпорації Майкрософт ми дуже дбаємо про покращення веб-продуктивності, і ми досягаємо прогресу в цьому з кількох напрямків:
Зі свого власного досвіду ми знаємо, що для складних програм потрібна складна архітектура, яка іноді покладається на кілька вікон, iframe або робочих потоків. Щоб усунути уповільнення, яке може спричинити ці численні паралельні контексти, ми пропонуємо нову функцію для веб-розробників: API синхронізації затриманих повідомлень.
Якщо ви веб-розробник, продовжуйте читати, щоб дізнатися більше про пропозицію API синхронізації затриманих повідомлень, і повідомте нам, чи може це допомогти вам зробити вашу власну веб-програму швидшою, або поділіться способами покращення API.
Що спричиняє затримки міжконтекстних повідомлень?
Затримки можуть виникати, коли програма обмінюється великою кількістю повідомлень між різними контекстами, такими як головне вікно програми, робочі потоки або iframe. Якщо ці повідомлення потрапляють у чергу й не обробляються негайно, виникають затримки.
Ці затримки можуть погіршити взаємодію з користувачем, оскільки програма не реагує. Хоча спостерігати затримку легко, виявити її першопричину складно з поточними інструментами розробки.
Давайте розглянемо три типи затримок, які можуть виникати під час обміну повідомленнями між контекстами за допомогою postMessage() API та як API синхронізації затриманих повідомлень може допомогти діагностувати їх першопричину.
Сповільнення 1 – приймаючий контекст зайнятий
Як показано на наведеній нижче схемі, контекст, до якого ви надсилаєте повідомлення, може обробляти довге синхронне завдання, фактично блокуючи його потік, спричиняючи до того, як ваше повідомлення потрапляє в чергу до того, як його можна буде обробити:

Щоб зрозуміти, чи зайнятий одержувач повідомлення іншими справами, потрібно знати, як довго повідомлення було заблоковано.
Для цього API синхронізації затриманих повідомлень представляє blockedDuration властивість, яка представляє час, протягом якого повідомлення чекало в черзі перед обробкою.
Уповільнення 2 – Черга завдань перевантажена
Ще одна можлива причина уповільнення обміну повідомленнями між документами полягає в тому, що черга завдань контексту перевантажена великою кількістю коротких завдань.
У головному потоці веб-сторінки це часто трапляється, коли чергу насичено високопріоритетними завданнями, такими як взаємодія з користувачем, обробка мережі та інші внутрішні системні накладні завдання, як-от навігація, завантаження та рендеринг. У воркері може виникнути перевантаження, коли за короткий проміжок часу опубліковано багато повідомлень. В обох випадках завдання або повідомлення надходять швидше, ніж вони можуть бути оброблені, створюючи відставання, яке затримує наступні повідомлення, включно з тими, які можуть бути чутливими до часу.
Хоча кожне окреме завдання недовге, разом вони накопичуються та спричиняють перевантаження, що фактично діє як одне довге завдання.

Щоб допомогти діагностувати цю ситуацію, API синхронізації затриманих повідомлень представляє taskCount і scriptTaskCount властивості, щоб показати, скільки завдань блокували повідомлення.
Уповільнення 3 – накладні витрати на серіалізацію та десеріалізацію
Перш ніж перетинати межі між контекстами, повідомлення повинні бути серіалізовані, а потім знову десеріалізовані при отриманні.
Ці операції відбуваються синхронно в тих самих потоках, де надсилаються та отримуються повідомлення. Таким чином, серіалізація та десеріалізація повідомлень можуть призвести до помітних накладних витрат, особливо при надсиланні великої кількості даних postMessage().

Хоча операції серіалізації та десеріалізації є внутрішніми для веб-переглядача, і ви не можете їх змінити, Delayed Message Timing API надає serialization і deserialization властивості для точного вимірювання їх тривалості.
Використання API синхронізації затриманих повідомлень
API працюватиме з вікнами, вкладками, фреймами iframe або worker, а також охоплюватиме обмін повідомленнями між документами, обмін повідомленнями між worker/document, обмін повідомленнями каналу та канали трансляції.
Для повного аналізу часу проходження туди й назад вам потрібно буде співвіднести записи продуктивності, які ви збираєте з контекстів відправника та отримувача. Щоб дізнатися більше, перегляньте пояснювач.
У наступному фрагменті коду показано, як використовувати запропонований API:
// Create a PerformanceObserver instance.
const observer = new PerformanceObserver((list) => {
console.log(list.getEntries());
});
// Start observing "delayed-message" Performance entries.
observer.observe({type: 'delayed-message', buffered: true}); А ось приклад властивостей, доступних для відповідного запису продуктивності «повідомлення із затримкою»:
{
"name": "delayed-message",
"entryType": "delayed-message",
"startTime": 154.90000009536743,
"duration": 169,
"traceId": 4,
// The type of message-passing event.
"messageType": "cross-worker-document",
// The timestamp for when the message was added to the task queue.
"sentTime": 155,
// The timestamps for when the receiving context started and stopped
// processing the message.
"processingStart": 274.90000009536743,
"processingEnd": 324.7000000476837,
// The time the message spent waiting in the receiver's task queue.
"blockedDuration": 119.90000009536743,
// The time needed to serialize and deserialize the message.
"serialization": 0,
"deserialization": 0,
// The number of queued tasks blocking the postMessage event.
"taskCount": 38,
// The number of entry-point JavaScript tasks, including those with
// a duration lower than 5ms.
"scriptTaskCount": 2,
// The time needed to run all script.
"totalScriptDuration": 119,
// The list of PerformanceScriptTiming instances that contribute to the
// delay.
"scripts": [
{
"name": "script",
"entryType": "script",
"startTime": 154.90000009536743,
"duration": 119,
"invoker": "DedicatedWorkerGlobalScope.onmessage",
"invokerType": "event-listener",
"windowAttribution": "other",
"executionStart": 154.90000009536743,
"forcedStyleAndLayoutDuration": 0,
"pauseDuration": 0,
"sourceURL": "...",
"sourceFunctionName": "runLongTaskOnWorker",
"sourceCharPosition": 267
}
],
// The PerformanceMessageScriptInfo instance which provides details
// about the script that sent the message.
"invoker": {
"name": "invoker",
"sourceURL": "...",
"sourceFunctionName": "sendMessage",
"sourceCharPosition": 531,
"sourceColumnNumber": 14,
"sourceLineNumber": 13,
"executionContext": {
"name": "",
"type": "window",
"id": 0
}
},
// The PerformanceMessageScriptInfo instance which provides details
// about the script that handled (or is handling) the message.
"receiver": {
"name": "receiver",
"sourceURL": "...",
"sourceFunctionName": "runLongTaskOnWorker",
"sourceCharPosition": 267,
"sourceColumnNumber": 41,
"sourceLineNumber": 9,
"executionContext": {
"name": "",
"type": "dedicated-worker",
"id": 1
}
}
} Дайте нам знати, що ви думаєте
API синхронізації затриманих повідомлень знаходиться на ранніх стадіях, і ми хотіли б почути ваші відгуки про цю пропозицію. Можуть існувати додаткові сценарії, коли сьогодні у ваших програмах відбуваються міжконтекстні уповільнення, і якщо ви поділитеся з нами своїм досвідом, це допоможе нам розробити правильний API для вас.
Перегляньте нашу пропозицію та повідомте нам свої відгуки, відкривши нову проблему на репо MSEdgeExplainers.
