Поддерживает ли Node.js parallelism?
Я больше искал разницу между concurrency и parallelism. Я наткнулся на беседу на YouTube, которую дал Роб Пайк, говоря о различиях между concurrency и parallelism. Его разговор был в контексте языка Google Go. Из того, что я понимаю, concurrency - это способ управления несколькими вещами, но parallelism - это физическое выполнение нескольких вещей одновременно.
Из того, что я также понимаю, Node.js работает как процесс с одним потоком. Итак, хотя Node поддерживает concurrency с тем, как он реализует обратные вызовы и т.д., Обладает ли он способностью выполнять параллельное выполнение задач? Можно ли настроить несколько потоков на отдельных процессорах?
Ответы
Ответ 1
Узел может поддерживать "Параллелизм" через модули Cluster
или child_process
, упакованные в Core API Nodejs. Оба эти модуля создают дополнительные процессы, а не дополнительные потоки.
Потоки создаются и управляются, иногда в пуле, "под капотом" с помощью libuv
, который node
реализует и использует для выполнения асинхронных операций, таких как чтение из файла. Вы не можете явно создать поток из своего исполняемого Javascript. Вы можете прочитать больше о libuv
на следующих ресурсах
Кроме того, это отличный вопрос о потоках и пуле, в котором много деталей.
Cluster
используется для распределения рабочей нагрузки Сервера по нескольким ядрам и при этом позволяет им совместно использовать порт. Однако Cluster
использует child_process.fork()
под капотом и обменивается данными через межпроцессное взаимодействие. Подробнее о Cluster
вы можете прочитать в Документах по API ядра Nodejs.
child_process
предлагает несколько различных способов распараллеливания работы через exec()
, spawn()
или fork()
. Родительский процесс может взаимодействовать с дочерним процессом, используя межпроцессное взаимодействие через каналы.
По сути, Node хочет, чтобы вы использовали цикл обработки событий и оставили управление потоками libuv
. Вот почему так легко создать код, который обычно требует мер блокировки и безопасности потоков. Если вы должны выполнять работу, требующую тяжелой работы или значительного количества блокирующих (синхронных) работ, то вы можете использовать child_process
, чтобы снять эту работу. Если вам нужно масштабировать веб-приложение по ядрам, используйте Cluster
.
Ответ 2
Если я не ошибаюсь, вы ищете нечто вроде многопоточности и/или вычисления нескольких вещей одновременно.
Несколько выполнения сразу
SIMD начинает искать свой путь в браузерах, а реализация Node не отстает. Посмотрите node-simd или MDN SIMD (браузеры).
SIMD по-прежнему экспериментальна и работает только на поддерживаемых процессорах на данный момент (очевидно, поскольку не все процессоры имеют эту функциональность). Он выполняет сразу несколько действий, примером сравнения обычного JS с SIMD JS будет:
// Normal addition, 4 actions are executed.
var a = [1, 2, 3, 4];
var b = [5, 6, 7, 8];
var c = [];
c[0] = a[0] + b[0];
c[1] = a[1] + b[1];
c[2] = a[2] + b[2];
c[3] = a[3] + b[3];
c; // Array[6, 8, 10, 12]
// SIMD execution - all additions are processed simultaenously through the CPU
var a = SIMD.Float32x4(1, 2, 3, 4);
var b = SIMD.Float32x4(5, 6, 7, 8);
var c = SIMD.Float32x4.add(a,b);
c; // Float32x4[6, 8, 10, 12]
Многопоточность
Что касается многопоточности, то webworkers
уже существует в среде браузера. Это портировано до Node полностью в соответствии с спецификацией HTML, как показано в этом репозитории.
Здесь хорошее объяснение относительно того, почему webworkers
было даже перенесено на Node, в первую очередь, поскольку вы уже можете запускать дочерние процессы в других потоков и других процессоров с модулем child_process
. node-webworker
- отличный модуль, так как каждый процесс запускается внутри его контекста и в своем собственном процессе node
, поэтому он действительно многопоточен с node.
Итак, чтобы запускать разные процессы на разных процессорах, вы должны либо принять node-webworker
, либо использовать child_process
для создания других потоков для одновременного выполнения отдельных действий с разными ядрами ЦП. node-webworker
может прослушивать события, используя знакомый API postMessage
, а child_process
будет связываться через stdin / stdout / stderr
.
Надеюсь, что ответит на ваш вопрос:)
Ответ 3
Выполнение нескольких потоков в отдельных процессорах на одном хост-компьютере может быть достигнуто путем использования собственных модулей Node os
и cluster
. Ниже приведен простой надуманный пример
const cluster = require('cluster');
const os = require('os');
((port) => {
if (cluster.isMaster) {
// fork the process
os.cpus().forEach((cpu) => {
cluster.fork();
});
} else {
// if we're not in the master thread, start the HTTP server
http.createServer((req, res) => {
// Handle request
}).listen(port, () => {
console.log('The server is listening on port ${port}');
});
}
})(3000)