Существует много путаницы по поводу конкурентности и параллелизма. Некоторые люди используют эти термины как взаимозаменяемые, но на самом деле они означают две разные вещи. Конкурентность — это когда выполнение двух или более задач может начинаться, выполняться и завершаться в частично совпадающие (накладывающиеся друг на друга) периоды времени. Это вовсе не означает, что они будут выполняться одновременно, но их можно чередовать так, чтобы в любой момент времени всегда выполнялась одна задача. Приведем пример Официант принимает заказ от клиента со столика 1 и ждет, пока он будет готов. После того как заказ будет готов, он выдает заказанные блюда клиентам. Затем переходит к следующему столу 2 клиента принимает заказ и идет на кухню, ожидая, пока он будет готов, после чего отдает еду клиенту. Эффективно ли это? НЕТ, потому что официант ничем не занимается, пока заказ не будет готов. Теперь официант идет к столу 1, принимает заказ и передает его на кухню, возвращается к столу 2, принимает заказ и передает его на кухню. Здесь официант не ждет, пока заказ будет готов, он идет принимать следующий заказ, пока еда готовится. Когда все будет готово, он подаст блюда на все столы. При этом, мы не увеличили количество официантов. Аналогично происходит, когда мы не увеличиваем количество потоков, но ускоряем процесс, сокращая время простоя. Работа с множеством вещей в одно и то же время. Это процесс конкурентности. Пример: во время приготовления пищи вам звонят, вы отвечаете на звонок, в то же время раздается сигнал кухонной плиты, вы возвращаетесь, выключаете плиту и снова отвечаете на звонок. Вы не выполняете что-то одно, а делаете две вещи одновременно, но по очереди. Параллелизм — это когда две или более задач могут действительно выполняться одновременно. Чтобы это произошло, задачи должны запускаться на разных процессорах или ядрах. Приведем пример Пока вы готовите еду, звонит телефон, ваша мама отвечает на звонок. Здесь две разные вещи происходят с двумя людьми, но в одно и то же время. Почему так важно понимать разницу? Параллелизм важен, потому что он позволяет структурировать код таким образом, чтобы эффективно использовать ресурсы. Параллелизм важен, потому что он может значительно повысить производительность за счет выполнения нескольких действий одновременно. Если вы пишете код, который будет выполняться на одном процессоре или ядре, то вам необходимо знать о конкурентности. Если ваш код будет выполняться на нескольких процессорах или ядрах, то нужно рассмотреть параллелизм. Однопоточный процесс — это выполнение запрограммированных инструкций в одной последовательности. Приложение имеет следующий набор инструкций: Инструкция A Инструкция B Инструкция C Если этот набор инструкций выполняется в однопоточном процессе, то это будет выглядеть следующим образом: Многопоточный процесс — это выполнение запрограммированных инструкций в нескольких последовательностях. Поэтому инструкциям не придется ждать завершения, если только некоторые из них не сгруппированы в разные последовательности. NodeJS является однопоточной платформой. Это означает, что он может обрабатывать только один запрос за один раз. Пример: Приняв заказ со стола 1 и передав его на кухню, официант идет к столу 2. В то время когда он принимает заказ со стола 2, еда для стола 1 уже готова, но официант не может сразу же подойти и передать готовое блюдо столу 1, он должен закончить обработку заказа со стола 2 и затем передать его на кухню. И только после этого он сможет передать готовое блюдо столу 1. Веб-сервер NodeJS поддерживает ограниченный пул потоков (limited Thread Pool) для обслуживания клиентских запросов. Многочисленные клиенты делают множественные запросы к NodeJS-серверу. NodeJS получает эти запросы и помещает их в EventQueue. Сервер NodeJS имеет внутренний компонент, называемый EventLoop, который представляет собой бесконечный цикл, принимающий запросы и обрабатывающий их. Этот EventLoop является однопоточным. Другими словами, EventLoop является слушателем для EventQueue. Событийно-ориентированная модель очень эффективна и позволяет NodeJS с легкостью обрабатывать тысячи одновременных запросов. Node.js использует две концепции Неблокирующий ввод/вывод Асинхронный Всякий раз, когда клиент посылает запрос, одиночный поток будет отправлять этот запрос кому-то другому. Текущий поток не будет занят обработкой этого запроса. Существуют воркеры, работающие на сервере. Сервер посылает запрос воркеру, тот дальше пересылает его другому серверу и ждет ответа. Тем временем, если поступит еще один запрос, поток отправит его другому воркеру, а тот будет ждать ответа от другого сервера. Таким образом, одиночный поток всегда будет доступен для приема запросов от клиента. Он не будет их блокировать. При традиционной многопоточной модели запросов/ответов каждый клиент получает отдельный поток, в то время как, как и в случае с NodeJS, более простые запросы обрабатываются непосредственно EventLoop. Это оптимизирует ресурсы пула потоков, и нет необходимости создавать потоки под каждый запрос клиента. Скоро состоится открытое занятие, на котором обсудим проблему производительности в NodeJS. Найдем причины и способы ее решения. Если интересно, регистрируйтесь по ссылке.