Web Workers
Добавьте производительности своим Web приложениям
Сергей Мелашич
Agilie
Сергей
Мелашич
web разработчик компании Agilie
SergeyMell
Seroga.Mell
Sergey Melashych
sergey.mell@agilie.com
преподаватель school.agilie.com
Мы живем во многопоточном мире
World
Software
JavaScript
Мир JavaScript
Мир JavaScript
CORE
CORE
CORE
CORE
Мир JavaScript
api.post('/login', userData)
.then(response => {
// Success stuff
}, error => {
// Error stuff
});
// Other stuff
APP THREAD
Action 1
Action 2
Action 3
Waiting for the response
Проблема однопоточности
CORE
CORE
CORE
CORE
Рендеринг чуть подробнее
Сколько времени у нас есть?
60 fps
16 ms
8 - 10 ms
"Тяжелые" операции
Обработка больших структур данных
Обработка изображений / звука
Генерация больших таблиц
Визуализация данных
...
Пример "тяжелой" операции
Решение?
1. setTimeout
2. iframe
3. Web Worker
Поддержка браузерами
Особенности Web Workers
1. Хранится в отдельном файле и запускается
как отдельный процесс
if (window.Worker) {
const myWorker = new Worker("hard_worker.js");
}
2. Взаимодействие осуществляется посредством сообщений
myWorker.postMessage(data);
myWorker.onmessage = (event) => {
console.log(event.data);
};
Особенности Web Workers
3. Нет доступа к DOM
4. Нет доступа к document, window, parent
5. Глобальный контекст доступен посредством self
Многопоточное исполнение
APP THREAD
WORKER THREAD
const myWorker =
new Worker("hard_worker.js");
myWorker.onmessage = ...
myWorker.postMessage(...);
renderResults(event.data);
self.onmessage = ...;
const result =
hardWork(event.data);
self.postMessage(result);
Блокировка рендеринга с решением
Shared Worker
const sharedWorker = new SharedWorker("shared.js");
sharedWorker.port.addEventListener("message", event => {
// Subscribing Event
}, false);
sharedWorker.port.start();
sharedWorker.port.postMessage(data);
Передача данных в Web Worker
1. Структурное клонирование (structured cloning)
myWorker.postMessage(arrayOfData);
2. Передаваемые объекты (transferable objects)
myWorker.postMessage(arrayOfData, [arrayOfData]);
3. Широковещательный канал (broadcast channel)
let channel = new BroadcastChannel('channel-name');
channel.postMessage(data);
4. Общая память (shared memory)
const sharedBuffer = new SharedArrayBuffer(40);
myWorker.postMessage(sharedBuffer);
Библиотеки для работы
с Web Workers
Parallel.js
Hamsters.js
Web Workers во фреймворках
Web Workers во Vue.js
this.$worker.run((arg) => {
return `Hello, ${arg}!`;
}, ['World'])
.then(result => {
console.log(result);
})
.catch(e => {
console.error(e);
});
https://github.com/israelss/vue-worker
Web Workers в React.js
https://github.com/web-perf/react-worker-dom
number of nodes
fps
react-renderer
react-worker-dom
Web Workers в Angular
UI THREAD
WORKER THREAD
Бизнес
логика
Пользовательское событие
postMessage('call');
Связанные данные
postMessage(data);
Как это сделать?
import '../polyfills.ts';
import '@angular/core';
import '@angular/common';
import {platformWorkerAppDynamic} from '@angular/platform-webworker-dynamic';
import { AppModule } from '../app/app.module';
platformWorkerAppDynamic().bootstrapModule(AppModule);
bootstrapWorkerUi('../webworker.bundle.js');
import { WorkerAppModule } from '@angular/platform-webworker';
webworker.ts
main.ts
app.module.ts
Angular на стероидах WebWorker-ах
А как же роутинг?
@NgModule({
...,
providers: [
...,
{provide: APP_BASE_HREF, useValue: '/'},
WORKER_APP_LOCATION_PROVIDERS,
]
});
app.module.ts
bootstrapWorkerUi(
'../webworker.bundle.js',
WORKER_UI_LOCATION_PROVIDERS
);
main.ts
Тестирование производительности
fps
интенсивность мутаций
Angular clean
Angular worker
Полезные ссылки
Благодарю за внимание
Пожалуйста, разбудите спящих соседей
SergeyMell
Seroga.Mell
Sergey Melashych
sergey.mell@agilie.com
fwdays 2018
By Sergey Mell
fwdays 2018
- 2,053