SlideShare a Scribd company logo
Многопоточность в JS :

Миф или реальность?
1
SAFE HARBOR
• Контент этого доклада не является
единственной истинной в последней инстанции.
• Если вы увидели что-то, что считаете
неправдой - не бойтесь сказать об этом
докладчику.
2
Кто я такой
• Меня зовут Александр.
• Software Engineer в Aeneas Platform.
• Студент в КНУ, кибернетика.
• Пишу на Scala, Java/Kotlin, C++ и JS.
• github.com/Fly-Style
3
О чем доклад
• Многопоточность

+ производительности

- сложность кода
• JS и многопоточность
4
План доклада
Memory Model
Synchronization Actions
Thread Design
Allocations
Garbage Collection
DOM Interaction
5
Текущее положение дел
• JS-engines – однопоточные.
• Неблокирующий I/O в одном потоке.
• Web-worker – не панацея.
• ChakraCore !-> napa.js.
6
Thread support : Pros
• Несколько выполняемых задач одновременно на
железе.
• Скорость выполнения программы
увеличивается.
7
Пример
!// 1

new Thread(function() { 

console.log("Hello, threads!"); 

}).join();
!// 2

new Thread(() !=> { 

console.log("Hello, lambdas inside!"); 

}).join();
8
Thread support : Pros
• Специальные структуры данных в языке для
пользовательских приложений.
• Многопоточность в помощь асинхронному
программированию.
9
Пример
async function task1() = { … };
async function task2() = { … };
const finalResult = task(await task1(), await task2());
10
Пример
const threadPool = new ThreadPool(2);
const result1 = threadPool.accept(task1);
const result2 = threadPool.accept(task2);
const finalResult = task(await result1,await result2);
11
Thread support : Cons
• Усложняется код.
• Синхронизация потоков над общими данными.
• Сложно для восприятия.
12
Давайте пофантазируем…
• Что делать инженерам V8 (JSCore, ChakraCore,
SpiderMonkey, TeaVM)?
• Сначала обратимся к основам CS.
13
Архитектура фон Неймана
• Память однородна : команды и данные
хранятся в одной памяти.
• Адресность памяти : память разделена на
нумерованные ячейки.
• Программное управление памятью : все
вычисления должны быть представлены в виде
программы, состоящей из последовательности
управляющих слов — команд.
14
Как устроена память
• Процессор (708 байт в x86-64)
• Кэши L1-L3 (1 - 16 Mб)
• RAM (4 - 64 Гб) – доступна разработчикам.
• Внешние накопители
15
Но люди не пишут
прямые команды
процессору!
16
Люди оперируют
моделями!
17
Абстрактная машина
• Абстрактная машина исполняет код на
высокоуровневом языке.
• Вас не должно волновать, каким именно
образом достигается результат.
• А вот инженеров этой самой машины - как раз
очень должно волновать.
18
Memory Model
Synchronization Actions
Thread Design
Allocations
Garbage Collection
DOM Interaction
19
Memory Model
• В последовательных программах все команды
исполняются последовательно.
• Обращения к памяти тоже происходят
последовательно.
• В многопоточных же программах все иначе : 

потоки обращаются к общей памяти, из-за чего
ожидаемого результата может и не быть!
20
Memory Model
• Формализованная модель памяти нужна для
того, чтобы специфицировать поведение
программы отношениями порядка записи и
чтения.
• А именно ответить на вопрос :
• Какое конкретное значение может увидеть
конкретное чтение в программе?
21
IRIW
atomic var a, b
Thread 1 Thread 2 Thread 3 Thread 4
a = 1 b = 1
let r1 = a
let r2 = b
let r3 = b
let r4 = a
• Какие допустимые значения кортежа 

(r1, r2, r3, r4)?
22
IRIW
atomic var a, b
Thread 1 Thread 2 Thread 3 Thread 4
a = 1 b = 1
let r1 = a
let r2 = b
let r3 = b
let r4 = a
• Например, (r1, r2, r3, r4) = (0, 1, 0, 1)
нежелателен, потому что теряется порядок
применения операций load / store.
23
IRIW
atomic var a, b
Thread 1 Thread 2 Thread 3 Thread 4
a = 1 b = 1
let r1 = a
let r2 = b
let r3 = b
let r4 = a
• В зрелых моделях памяти это ограничение
называется «multiple copy atomicity» – запись
видят или все потоки, или никакой из потоков.
24
Memory Model
• Модель памяти про определение отношений
порядков между действиями чтения/записи в
программе
• … и наложения ограничений на исполнение
программы через т.н. «барьеры чтения/записи».
25
Без ограничений на исполнение программы в каждом из
перечисленных типов порядков, получим С89 в миниатюре. 



Поэтому это нам нужно (глава 27)
26
Memory Model
Synchronization Actions
Thread Design
Allocations
Garbage Collection
DOM Interaction
27
Lock
• Для блокировки необходимы объекты
синхронизации.
• Такими объектами являются локи.
28
29
Lock
• Для блокировки необходимы объекты
синхронизации.
• Такими объектами являются локи.
• Примерами локов являются : mutex,
lock_guard, unique_lock из С++.
30
Пример Lock
let lock = new Mutex();



!//…
lock.lock();



doSomeTask();



lock.unlock();
31
Monitors
• Условные переменные (conditional variable) или
монитор.
• Храним информацию о блокировке в метаинформации
объекта, например.
32
Пример
let condVar = new СonditionalVariable();
condVar.wait(lock);



doSomeTask();



condVar.notify(); !// Notify one thread or promise.
condVar.notifyAll(); !// Notify all threads and promises.
33
Lockless / Atomic
• Хитрые хардверщики в своих изыскахЪ
подвезли нам возможность за одну инструкцию
дешево, безопасно и почти безболезненно
сделать запись в память.
• Правда есть одно «но» : применимо только для
примитивов и ссылок.
34
Пример
let atomicInt = new AtomicInteger();
atomicInt.compareAndExchange(1, 2);
!// !=> true, atomic = 2.
atomicInt.compareAndExchange(1, 3);
!// !=> false, atomic = 2.



35
Lockless / Atomic
mov %eax, 0х1

mov %rbx, 0х2

mov %rcx, 0х1

cmpxchg %rcx, %rbx
36
Lockless / Atomic : Pros
• Лучше масштабируемость.
• Применяется в lock-free структурах данных, где
важна производительность.
37
Transactional Memory
• Технология транзакционной памяти упрощает
параллельное программирование, выделяя группы
инструкций в атомарные транзакции.
• В этом случае мы считаем, что потоки работают
независимо друг от друга и в редких случаях изменяют
одни и те же данные.
38
И вот если принести вот это все
абстрактному инженеру этой самой
виртуальной машины для JS, то …
39
40
Lock`и & Atomic`и - необходимая часть языка для
того, чтобы работа с многопоточностью не
напоминала АДЪ.



Посему, оно нам надо.
41
Memory Model
Synchronization Actions
Thread Design
Allocations
Garbage Collection
DOM Interaction
42
Дизайн потоков
• Поток – это отдельная единица выполнения
кода, связанная с остальными только общей
памятью.
• Каждый поток должен иметь свои виртуальные
регистры, stack pointer и program counter.
43
Выбор «бэкэнда» для
потока
• Есть два варианта :
• Kernel thread – полноценная и отдельная нить
исполнения.
• Fiber a.k.a. Волокна – легкая нить, не
выполняется явно параллельно!
44
Варианты реализации
• Нативная вытесняющая многопоточность 

(Java, C#)
• Кооперативная многопоточность внутри VM

(Erlang).
• Виртуальная многопоточность (Python, Ruby)
45
Варианты реализации
• Нативная вытесняющая многопоточность 

(Java, C#)
• Кооперативная многопоточность внутри VM

(Erlang).
• Виртуальная многопоточность (Python, Ruby)
46
Нативная вытесняющая
многопоточность
• Каждый поток выполняется поверх
назначенному ему нативному потоку ОС.
• Переключение и планировка потоков
осуществляется планировщиком ОС.
• Так как переключения VM не контролирует,
часто внутри кода VM нужны критические
секции.
47
Дизайн класса потока
• Если дизайнить Thread как класс, то в прототипе
необходимо определить :
1. конструктор с функцией в качестве параметра, в
которой будет определён блок с параллельным
кодом.
2. метод, который будет исполнять параллельный код.
3. метод, который будет дожидаться конца
исполнения и «парковать» освободившийся поток.
48
Дизайн класса потока
class Thread {



constructor(runner: function) {…}

join(thread: Thread) {…}

start() {…}



}
49
Пример
!// 1

new Thread(() !=> { 

console.log("Hello, Thread!"); 

}).join();

!// !=> Hello, Thread!



!// 2

let print = () !=> console.log("Hello");

let thread = new Thread(print).start();

thread.join();

!// !=> Hello!
50
Memory Model
Synchronization Actions
Thread Design
Allocations
Garbage Collection
DOM Interaction
51
Выделение памяти :
проблемы
• Диспетчеры памяти обычно пишутся на языке,
отличном от языка таргета (С++ и JS).
• Поэтому выделение памяти одному потоку имеет
более-менее оправданную скорость, а вот многим -
скорее всего нет.
52
Выделение памяти :
проблемы
• Для оптимизации надо позволить потокам выделять
целые блоки памяти для своих нужд.
• Такие блоки памяти называются Thread-Local
Allocation Buffers (a.k.a. TLAB).
53
Bump pointer allocation
• Аллоцируем по адресу текущего указателя TLAB +
размер объекта.
• Если мы запрашиваем выделение объекта, который
превышает размер TLAB, мы выделяем напрямую.
54
TLAB уже реализованы.
Осталось только научить V8 отдавать эти TLAB 

в рантайм, а не только GC.
55
Memory Model
Synchronization Actions
Thread Design
Allocations
Garbage Collection
DOM Interaction
56
VM safepoint : Ideas
• Иметь безопасный доступ к памяти.
• Кооперативно остановить потоки.
• Знать, когда нам точно надо уйти на GC паузу.
57
VM safepoint : Problems
• Остановить потоки не так-то и просто.
• Во время критической секции, например.
• Или во время т.н. «короткого» цикла.
58
GC : Problems
• Определение rootset становится еще большей
проблемой : надо сканировать стеки всех потоков.
• Анализ достижимости объектов и hidden классов.
• Достижимость кода из Code Space.
59
Reachability Analysis
function f() {

let person = {age: 21, name: "Alex"};

!// GC safepoint

register(person);

}



60
Это не полный список изменений.
Полный список вызовет у вас желание плакать и
плавать в Океане Отчаянья.
Инженеров тоже.
61
Memory Model
Synchronization Actions
Thread Design
Allocations
Garbage Collection
DOM Interaction
62
DOM Interaction
• ConcurrentAccessError при попытке записи из
пользовательских потоков.
• Также запретить concurrent доступ ко всем
глобальным объектам.
• Но console, пожалуй, стоит пожалеть :)
63
В моде глобальное состояние приложения.
Concurrent DOM Interaction не нужен 🙁.
64
Conclusion
65
• Создавать виртуальные машины сложно!
• Вносить изменения в VM ещё сложнее!
• Мечтать – приятно и очень познавательно!
• Многопоточность – сложно!
• Бенефит от использования перевешивает минусы!
66
Useful books and links
1. Блог WebKit о JS Concurrency.
2. Xiao Feng Li – Advanced Design and Implementation of VM.
3. Richard Jones, Antony Hosking, Eliot Moss – GC Handbook.
67
Q/A?
68

More Related Content

PPTX
Artisto: опыт запуска нейросетей в production / Эдуард Тянтов (Mail.ru Group)
PDF
Введение в архитектуры нейронных сетей / HighLoad++ 2016
PDF
Алексей Федоров
PDF
Java Platform Performance BoF
PDF
Современные архитектуры диалоговых систем / Анатолий Востряков (Segmento)
PDF
Operden1
PPTX
Производительность Unity3D: подводные камни / Алексей Чубарь (BIT.GAMES)
ODP
Top10 доводов против языка Ruby
Artisto: опыт запуска нейросетей в production / Эдуард Тянтов (Mail.ru Group)
Введение в архитектуры нейронных сетей / HighLoad++ 2016
Алексей Федоров
Java Platform Performance BoF
Современные архитектуры диалоговых систем / Анатолий Востряков (Segmento)
Operden1
Производительность Unity3D: подводные камни / Алексей Чубарь (BIT.GAMES)
Top10 доводов против языка Ruby

What's hot (20)

PPTX
Опыт эксплуатации большого проекта на Ruby
PPTX
Доклад в Mail.ru 01.11.12
PDF
Лев Валкин — Кое-что про Erlang
KEY
Что и почему писать на Erlang
PPTX
Modern neural net architectures - Year 2019 version
PPTX
Пишем самый быстрый хеш для кэширования данных
PPTX
Пайплайн машинного обучения на Apache Spark / Павел Клеменков (Rambler&Co)
KEY
Erlang for Yandex
PDF
Опыт использования Erlang в разработке многопользовательской игры
PDF
"Распределенные" вычисления на мобильных платформах. Зачем еще нужен "металли...
PDF
PDF
Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...
PPTX
Клиентская Java вне браузера. Делаем нативные клиенты на Java
PDF
Вебинар: Основы распараллеливания С++ программ при помощи OpenMP
PDF
Алексей Туля - А нужен ли вам erlang?
PDF
Erlang мгновенное просветление
PPTX
C++ Core Guidelines
PPTX
разработка бизнес приложений (8)
PPTX
BlackBox testing
Опыт эксплуатации большого проекта на Ruby
Доклад в Mail.ru 01.11.12
Лев Валкин — Кое-что про Erlang
Что и почему писать на Erlang
Modern neural net architectures - Year 2019 version
Пишем самый быстрый хеш для кэширования данных
Пайплайн машинного обучения на Apache Spark / Павел Клеменков (Rambler&Co)
Erlang for Yandex
Опыт использования Erlang в разработке многопользовательской игры
"Распределенные" вычисления на мобильных платформах. Зачем еще нужен "металли...
Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...
Клиентская Java вне браузера. Делаем нативные клиенты на Java
Вебинар: Основы распараллеливания С++ программ при помощи OpenMP
Алексей Туля - А нужен ли вам erlang?
Erlang мгновенное просветление
C++ Core Guidelines
разработка бизнес приложений (8)
BlackBox testing
Ad

Similar to Multithreading in JS. Myth or reality? (20)

PDF
Nonblocking algorithms/CAS/Atomics by Alexey Fyodorov
PDF
Иван Пузыревский — Введение в асинхронное программирование
PPTX
Asynchrony and coroutines
PDF
Node.js Меньше сложности, больше надежности Holy.js 2021
PPTX
Григорий Демченко, Асинхронность и неблокирующая синхронизация
PDF
Lecture1: Introduction to Parallel Computing
POTX
Как жить в согласии с SOLID?
PDF
Алексей Распопов "Будущее асинхронного программирования в ECMAScript"
PDF
Баба Яга против!
PDF
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
PPTX
Programming Java - Lection 06 - Multithreading - Lavrentyev Fedor
PPTX
Валерий Петров «Модель памяти .NET»
PDF
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
PPTX
PostSharp - Threading Model Library
PDF
PostSharp - Threading Model
PPTX
разработка серверов и серверных приложений лекция №2
PPTX
разработка серверов и серверных приложений лекция №2
PDF
Оптимизация программ для современных процессоров и Linux, Александр Крижановс...
PDF
Atomics, CAS and Nonblocking algorithms
PDF
Оптимизация производительности фронтенда / Игорь Алексеенко (HTML Academy)
Nonblocking algorithms/CAS/Atomics by Alexey Fyodorov
Иван Пузыревский — Введение в асинхронное программирование
Asynchrony and coroutines
Node.js Меньше сложности, больше надежности Holy.js 2021
Григорий Демченко, Асинхронность и неблокирующая синхронизация
Lecture1: Introduction to Parallel Computing
Как жить в согласии с SOLID?
Алексей Распопов "Будущее асинхронного программирования в ECMAScript"
Баба Яга против!
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
Programming Java - Lection 06 - Multithreading - Lavrentyev Fedor
Валерий Петров «Модель памяти .NET»
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
PostSharp - Threading Model Library
PostSharp - Threading Model
разработка серверов и серверных приложений лекция №2
разработка серверов и серверных приложений лекция №2
Оптимизация программ для современных процессоров и Linux, Александр Крижановс...
Atomics, CAS and Nonblocking algorithms
Оптимизация производительности фронтенда / Игорь Алексеенко (HTML Academy)
Ad

Multithreading in JS. Myth or reality?

  • 1. Многопоточность в JS :
 Миф или реальность? 1
  • 2. SAFE HARBOR • Контент этого доклада не является единственной истинной в последней инстанции. • Если вы увидели что-то, что считаете неправдой - не бойтесь сказать об этом докладчику. 2
  • 3. Кто я такой • Меня зовут Александр. • Software Engineer в Aeneas Platform. • Студент в КНУ, кибернетика. • Пишу на Scala, Java/Kotlin, C++ и JS. • github.com/Fly-Style 3
  • 4. О чем доклад • Многопоточность
 + производительности
 - сложность кода • JS и многопоточность 4
  • 5. План доклада Memory Model Synchronization Actions Thread Design Allocations Garbage Collection DOM Interaction 5
  • 6. Текущее положение дел • JS-engines – однопоточные. • Неблокирующий I/O в одном потоке. • Web-worker – не панацея. • ChakraCore !-> napa.js. 6
  • 7. Thread support : Pros • Несколько выполняемых задач одновременно на железе. • Скорость выполнения программы увеличивается. 7
  • 8. Пример !// 1
 new Thread(function() { 
 console.log("Hello, threads!"); 
 }).join(); !// 2
 new Thread(() !=> { 
 console.log("Hello, lambdas inside!"); 
 }).join(); 8
  • 9. Thread support : Pros • Специальные структуры данных в языке для пользовательских приложений. • Многопоточность в помощь асинхронному программированию. 9
  • 10. Пример async function task1() = { … }; async function task2() = { … }; const finalResult = task(await task1(), await task2()); 10
  • 11. Пример const threadPool = new ThreadPool(2); const result1 = threadPool.accept(task1); const result2 = threadPool.accept(task2); const finalResult = task(await result1,await result2); 11
  • 12. Thread support : Cons • Усложняется код. • Синхронизация потоков над общими данными. • Сложно для восприятия. 12
  • 13. Давайте пофантазируем… • Что делать инженерам V8 (JSCore, ChakraCore, SpiderMonkey, TeaVM)? • Сначала обратимся к основам CS. 13
  • 14. Архитектура фон Неймана • Память однородна : команды и данные хранятся в одной памяти. • Адресность памяти : память разделена на нумерованные ячейки. • Программное управление памятью : все вычисления должны быть представлены в виде программы, состоящей из последовательности управляющих слов — команд. 14
  • 15. Как устроена память • Процессор (708 байт в x86-64) • Кэши L1-L3 (1 - 16 Mб) • RAM (4 - 64 Гб) – доступна разработчикам. • Внешние накопители 15
  • 16. Но люди не пишут прямые команды процессору! 16
  • 18. Абстрактная машина • Абстрактная машина исполняет код на высокоуровневом языке. • Вас не должно волновать, каким именно образом достигается результат. • А вот инженеров этой самой машины - как раз очень должно волновать. 18
  • 19. Memory Model Synchronization Actions Thread Design Allocations Garbage Collection DOM Interaction 19
  • 20. Memory Model • В последовательных программах все команды исполняются последовательно. • Обращения к памяти тоже происходят последовательно. • В многопоточных же программах все иначе : 
 потоки обращаются к общей памяти, из-за чего ожидаемого результата может и не быть! 20
  • 21. Memory Model • Формализованная модель памяти нужна для того, чтобы специфицировать поведение программы отношениями порядка записи и чтения. • А именно ответить на вопрос : • Какое конкретное значение может увидеть конкретное чтение в программе? 21
  • 22. IRIW atomic var a, b Thread 1 Thread 2 Thread 3 Thread 4 a = 1 b = 1 let r1 = a let r2 = b let r3 = b let r4 = a • Какие допустимые значения кортежа 
 (r1, r2, r3, r4)? 22
  • 23. IRIW atomic var a, b Thread 1 Thread 2 Thread 3 Thread 4 a = 1 b = 1 let r1 = a let r2 = b let r3 = b let r4 = a • Например, (r1, r2, r3, r4) = (0, 1, 0, 1) нежелателен, потому что теряется порядок применения операций load / store. 23
  • 24. IRIW atomic var a, b Thread 1 Thread 2 Thread 3 Thread 4 a = 1 b = 1 let r1 = a let r2 = b let r3 = b let r4 = a • В зрелых моделях памяти это ограничение называется «multiple copy atomicity» – запись видят или все потоки, или никакой из потоков. 24
  • 25. Memory Model • Модель памяти про определение отношений порядков между действиями чтения/записи в программе • … и наложения ограничений на исполнение программы через т.н. «барьеры чтения/записи». 25
  • 26. Без ограничений на исполнение программы в каждом из перечисленных типов порядков, получим С89 в миниатюре. 
 
 Поэтому это нам нужно (глава 27) 26
  • 27. Memory Model Synchronization Actions Thread Design Allocations Garbage Collection DOM Interaction 27
  • 28. Lock • Для блокировки необходимы объекты синхронизации. • Такими объектами являются локи. 28
  • 29. 29
  • 30. Lock • Для блокировки необходимы объекты синхронизации. • Такими объектами являются локи. • Примерами локов являются : mutex, lock_guard, unique_lock из С++. 30
  • 31. Пример Lock let lock = new Mutex();
 
 !//… lock.lock();
 
 doSomeTask();
 
 lock.unlock(); 31
  • 32. Monitors • Условные переменные (conditional variable) или монитор. • Храним информацию о блокировке в метаинформации объекта, например. 32
  • 33. Пример let condVar = new СonditionalVariable(); condVar.wait(lock);
 
 doSomeTask();
 
 condVar.notify(); !// Notify one thread or promise. condVar.notifyAll(); !// Notify all threads and promises. 33
  • 34. Lockless / Atomic • Хитрые хардверщики в своих изыскахЪ подвезли нам возможность за одну инструкцию дешево, безопасно и почти безболезненно сделать запись в память. • Правда есть одно «но» : применимо только для примитивов и ссылок. 34
  • 35. Пример let atomicInt = new AtomicInteger(); atomicInt.compareAndExchange(1, 2); !// !=> true, atomic = 2. atomicInt.compareAndExchange(1, 3); !// !=> false, atomic = 2.
 
 35
  • 36. Lockless / Atomic mov %eax, 0х1
 mov %rbx, 0х2
 mov %rcx, 0х1
 cmpxchg %rcx, %rbx 36
  • 37. Lockless / Atomic : Pros • Лучше масштабируемость. • Применяется в lock-free структурах данных, где важна производительность. 37
  • 38. Transactional Memory • Технология транзакционной памяти упрощает параллельное программирование, выделяя группы инструкций в атомарные транзакции. • В этом случае мы считаем, что потоки работают независимо друг от друга и в редких случаях изменяют одни и те же данные. 38
  • 39. И вот если принести вот это все абстрактному инженеру этой самой виртуальной машины для JS, то … 39
  • 40. 40
  • 41. Lock`и & Atomic`и - необходимая часть языка для того, чтобы работа с многопоточностью не напоминала АДЪ.
 
 Посему, оно нам надо. 41
  • 42. Memory Model Synchronization Actions Thread Design Allocations Garbage Collection DOM Interaction 42
  • 43. Дизайн потоков • Поток – это отдельная единица выполнения кода, связанная с остальными только общей памятью. • Каждый поток должен иметь свои виртуальные регистры, stack pointer и program counter. 43
  • 44. Выбор «бэкэнда» для потока • Есть два варианта : • Kernel thread – полноценная и отдельная нить исполнения. • Fiber a.k.a. Волокна – легкая нить, не выполняется явно параллельно! 44
  • 45. Варианты реализации • Нативная вытесняющая многопоточность 
 (Java, C#) • Кооперативная многопоточность внутри VM
 (Erlang). • Виртуальная многопоточность (Python, Ruby) 45
  • 46. Варианты реализации • Нативная вытесняющая многопоточность 
 (Java, C#) • Кооперативная многопоточность внутри VM
 (Erlang). • Виртуальная многопоточность (Python, Ruby) 46
  • 47. Нативная вытесняющая многопоточность • Каждый поток выполняется поверх назначенному ему нативному потоку ОС. • Переключение и планировка потоков осуществляется планировщиком ОС. • Так как переключения VM не контролирует, часто внутри кода VM нужны критические секции. 47
  • 48. Дизайн класса потока • Если дизайнить Thread как класс, то в прототипе необходимо определить : 1. конструктор с функцией в качестве параметра, в которой будет определён блок с параллельным кодом. 2. метод, который будет исполнять параллельный код. 3. метод, который будет дожидаться конца исполнения и «парковать» освободившийся поток. 48
  • 49. Дизайн класса потока class Thread {
 
 constructor(runner: function) {…}
 join(thread: Thread) {…}
 start() {…}
 
 } 49
  • 50. Пример !// 1
 new Thread(() !=> { 
 console.log("Hello, Thread!"); 
 }).join();
 !// !=> Hello, Thread!
 
 !// 2
 let print = () !=> console.log("Hello");
 let thread = new Thread(print).start();
 thread.join();
 !// !=> Hello! 50
  • 51. Memory Model Synchronization Actions Thread Design Allocations Garbage Collection DOM Interaction 51
  • 52. Выделение памяти : проблемы • Диспетчеры памяти обычно пишутся на языке, отличном от языка таргета (С++ и JS). • Поэтому выделение памяти одному потоку имеет более-менее оправданную скорость, а вот многим - скорее всего нет. 52
  • 53. Выделение памяти : проблемы • Для оптимизации надо позволить потокам выделять целые блоки памяти для своих нужд. • Такие блоки памяти называются Thread-Local Allocation Buffers (a.k.a. TLAB). 53
  • 54. Bump pointer allocation • Аллоцируем по адресу текущего указателя TLAB + размер объекта. • Если мы запрашиваем выделение объекта, который превышает размер TLAB, мы выделяем напрямую. 54
  • 55. TLAB уже реализованы. Осталось только научить V8 отдавать эти TLAB 
 в рантайм, а не только GC. 55
  • 56. Memory Model Synchronization Actions Thread Design Allocations Garbage Collection DOM Interaction 56
  • 57. VM safepoint : Ideas • Иметь безопасный доступ к памяти. • Кооперативно остановить потоки. • Знать, когда нам точно надо уйти на GC паузу. 57
  • 58. VM safepoint : Problems • Остановить потоки не так-то и просто. • Во время критической секции, например. • Или во время т.н. «короткого» цикла. 58
  • 59. GC : Problems • Определение rootset становится еще большей проблемой : надо сканировать стеки всех потоков. • Анализ достижимости объектов и hidden классов. • Достижимость кода из Code Space. 59
  • 60. Reachability Analysis function f() {
 let person = {age: 21, name: "Alex"};
 !// GC safepoint
 register(person);
 }
 
 60
  • 61. Это не полный список изменений. Полный список вызовет у вас желание плакать и плавать в Океане Отчаянья. Инженеров тоже. 61
  • 62. Memory Model Synchronization Actions Thread Design Allocations Garbage Collection DOM Interaction 62
  • 63. DOM Interaction • ConcurrentAccessError при попытке записи из пользовательских потоков. • Также запретить concurrent доступ ко всем глобальным объектам. • Но console, пожалуй, стоит пожалеть :) 63
  • 64. В моде глобальное состояние приложения. Concurrent DOM Interaction не нужен 🙁. 64
  • 66. • Создавать виртуальные машины сложно! • Вносить изменения в VM ещё сложнее! • Мечтать – приятно и очень познавательно! • Многопоточность – сложно! • Бенефит от использования перевешивает минусы! 66
  • 67. Useful books and links 1. Блог WebKit о JS Concurrency. 2. Xiao Feng Li – Advanced Design and Implementation of VM. 3. Richard Jones, Antony Hosking, Eliot Moss – GC Handbook. 67