Архитектура Node.js

Лекция 04

Ресурсы


CPU

MEMORY

DISK

NETWORK

CPU bound

  • вычисление факториала
  • вычисление хэша
  • процесс шифрования
  • игровая арифметика

I/O bound

  • поиск по файлу
  • подсчет числа строк в файле
  • стримминг файла
  • копирование директории

Однопоточность

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

Не блокирующий I/O

Apache vs Nginx

Apache vs Nginx

Запросов в секунду в зависимости от количества одновременных подключений

Apache vs Nginx

Потребляемая память в зависимости от количества одновременных подключений

Операции в web-приложении

  • Чтение HTTP запроса I/O
  • Парсинг HTTP запроса CPU
  • Запрос в БД I/O
  • Запрос к API I/O
  • Генерация HTML CPU
  • Отправка HTML I/O

Неблокирующий I/O

Синхронный блокирующий I/O

Синхронный неблокирующий I/O

Асинхронный блокирующий I/O

Асинхронный неблокирующий I/O

I/O latency в циклах CPU

  • L1-кэш - 3 цикла
  • L2-кэш - 14 циклов
  • RAM - 250 циклов
  • Диск - 41 000 000 циклов
  • Сеть - 250 000 000 циклов
  • Latency Numbers Every Programmer Should Know / GitHub Gist

Reactor

Node.js

Node.js - Internals

Node.js - Event Loop

Node.js - Event Loop


f a() { console.log(3); }
console.log(1);
setTimeout(function () {
   console.log(2);
}, 3000);
a();
console.log(4);
        
Call Stack
main()
Tasks Queue:
API Workers:

Node.js - Event Loop


f a() { console.log(3); }
> console.log(1);
setTimeout(function () {
   console.log(2);
}, 3000);
a();
console.log(4);
        
Call Stack
console.log(1)
main()
Tasks Queue:
API Workers:

Node.js - Event Loop


f a() { console.log(3); }
> console.log(1);
setTimeout(function () {
   console.log(2);
}, 3000);
a();
console.log(4);
        
Call Stack
main()
Tasks Queue:
API Workers:

Node.js - Event Loop


f a() { console.log(3); }
console.log(1);
> setTimeout(function () {
   console.log(2);
}, 3000);
a();
console.log(4);
        
Call Stack
setTimeout(...)
main()
Tasks Queue:
API Workers:

Node.js - Event Loop


f a() { console.log(3); }
console.log(1);
> setTimeout(function () {
   console.log(2);
}, 3000);
a();
console.log(4);
        
Call Stack
main()
Tasks Queue:
API Workers:
timeout((callback), 3000)

Node.js - Event Loop


f a() { console.log(3); }
console.log(1);
setTimeout(function () {
   console.log(2);
}, 3000);
> a();
console.log(4);
        
Call Stack
a()
main()
Tasks Queue:
API Workers:
timeout((callback), 3000)

Node.js - Event Loop


> f a() { console.log(3); }
console.log(1);
setTimeout(function () {
   console.log(2);
}, 3000);
a();
console.log(4);
        
Call Stack
console.log(3)
a()
main()
Tasks Queue:
API Workers:
timeout((callback), 3000)

Node.js - Event Loop


> f a() { console.log(3); }
console.log(1);
setTimeout(function () {
   console.log(2);
}, 3000);
a();
console.log(4);
        
Call Stack
a()
main()
Tasks Queue:
API Workers:
timeout((callback), 3000)

Node.js - Event Loop


f a() { console.log(3); }
console.log(1);
setTimeout(function () {
   console.log(2);
}, 3000);
> a();
console.log(4);
        
Call Stack
main()
Tasks Queue:
API Workers:
timeout((callback), 3000)

Node.js - Event Loop


f a() { console.log(3); }
console.log(1);
setTimeout(function () {
   console.log(2);
}, 3000);
> a();
console.log(4);
        
Call Stack
main()
Tasks Queue:
(callback)
API Workers:

Node.js - Event Loop


f a() { console.log(3); }
console.log(1);
setTimeout(function () {
   console.log(2);
}, 3000);
a();
> console.log(4);
        
Call Stack
console.log(4)
main()
Tasks Queue:
(callback)
API Workers:

Node.js - Event Loop


f a() { console.log(3); }
console.log(1);
setTimeout(function () {
   console.log(2);
}, 3000);
a();
console.log(4);
        
Call Stack
main()
Tasks Queue:
(callback)
API Workers:

Node.js - Event Loop


f a() { console.log(3); }
console.log(1);
setTimeout(function () {
   console.log(2);
}, 3000);
a();
console.log(4);
        
Call Stack
Tasks Queue:
(callback)
API Workers:

Node.js - Event Loop


f a() { console.log(3); }
console.log(1);
> setTimeout(function () {
   console.log(2);
}, 3000);
a();
console.log(4);
        
Call Stack
(callback)
Tasks Queue:
API Workers:

Node.js - Event Loop


f a() { console.log(3); }
console.log(1);
setTimeout(function () {
>   console.log(2);
}, 3000);
a();
console.log(4);
        
Call Stack
console.log(2)
(callback)
Tasks Queue:
API Workers:

Node.js - Event Loop


f a() { console.log(3); }
console.log(1);
> setTimeout(function () {
  console.log(2);
}, 3000);
a();
console.log(4);
        
Call Stack
(callback)
Tasks Queue:
API Workers:

Node.js - Event Loop


f a() { console.log(3); }
console.log(1);
setTimeout(function () {
  console.log(2);
}, 3000);
a();
console.log(4);
        
Call Stack
Tasks Queue:
API Workers:

Node.js - Event Loop

http://latentflip.com/loupe

Node.js - Event Loop

Node.js - Event Loop

Node.js - Event Loop

console.log('script start');

setTimeout(function() {
  console.log('setTimeout');
}, 0);

Promise.resolve().then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});

console.log('script end');

// https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/
script start, script end, promise1, promise2,
setTimeout

Node.js - Event Loop

  • макро-задачи - выполняются по одной за один проход цикла
  • микро-задачи - на каждом проходе цикл выполняет все накопившееся

Node.js - Event Loop

  • макро-задачи (tasks queue): setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O, UI rendering
  • микро-задачи - process.nextTick, Object.observe, Promises (resolved)

Node.js и ES6+

  • node --v8-options
  • node -p process.versions.v8
  • http://node.green/