Что было бы лучше для одновременных задач на node.js? Волwindows? Веб-рабочие? или Threads?

Некоторое время назад я наткнулся на node.js, и мне это очень понравилось. Но вскоре я узнал, что ему не хватало возможности выполнять задачи с интенсивным использованием процессора. Итак, я начал поиск в Google и получил ответы на эту проблему: Fibers, Webworkers and Threads (thread-a-gogo). Теперь, какой из них использовать, это путаница, и один из них определенно необходимо использовать. В конце концов, какая цель иметь сервер, который просто хорош в IO и ничего больше? Нужны предложения!

ОБНОВИТЬ:

Я подумывал о том, чтобы уйти поздно; просто нуждаясь в предложениях по этому поводу. Теперь, о чем я думал, это: Давайте иметь некоторые streamи (используя thread_a_gogo или, возможно, веб-мастера). Теперь, когда нам нужно больше из них, мы можем создать больше. Но в процессе создания будет определенный предел. (не подразумевается системой, но, вероятно, из-за накладных расходов). Теперь, когда мы превысим предел, мы можем разблокировать новый узел и начать создавать streamи поверх него. Таким образом, он может продолжаться до тех пор, пока мы не достигнем определенного предела (в конце концов, процессы тоже имеют большие накладные расходы). Когда этот предел будет достигнут, мы начнем задачи очередей. Всякий раз, когда stream становится свободным, ему назначается новая задача. Таким образом, он может идти плавно.

Итак, это то, о чем я думал. Это хорошая идея? Я немного новичок во всем этом процессе и streamах, поэтому у меня нет опыта. Пожалуйста, поделитесь своими мнениями.

Благодарю. 🙂

У узла есть совершенно другая парадигма, и как только он правильно зафиксирован, легче увидеть этот другой способ решения проблем. Вам никогда не нужно несколько streamов в приложении Node (1), потому что у вас есть другой способ сделать то же самое. Вы создаете несколько процессов; но это очень сильно отличается от того, например, как работает appm веб-сервера Apache.

На данный момент давайте подумаем, что у нас есть только одно kernel ​​ЦП, и мы разработаем приложение (в порядке Узел), чтобы выполнить некоторую работу. Наша задача – обработать большой файл, работающий по содержимому побайтно. Лучший способ для нашего программного обеспечения – начать работу с начала файла, следовать за ним побайтам до конца.

– Эй, Хасан, я полагаю, вы либо новичок, либо очень старая школа со времен моего деда! Почему бы вам не создать несколько streamов и сделать их намного быстрее?

– У нас только одно kernel ​​процессора.

— И что? Создайте stream людей, сделайте это быстрее!

– Это не работает. Если я создам streamи, я буду делать это медленнее. Потому что я добавлю много накладных расходов на систему для переключения между streamами, пытаясь дать им простое количество времени и внутри моего процесса, пытаясь установить связь между этими streamами. В дополнение ко всем этим фактам мне также придется подумать о том, как разделить одну работу на несколько частей, которые можно сделать параллельно.

– Ладно, я вижу, вы бедны. Давайте использовать мой компьютер, он имеет 32 ядра!

– Вау, ты classный мой дорогой друг, спасибо тебе большое. Я ценю это!

Затем мы возвращаемся к работе. Теперь у нас есть 32 ядра процессора благодаря нашему богатому другу. Правила, которые мы должны соблюдать, только что изменились. Теперь мы хотим использовать все это богатство, которое нам дано.

Чтобы использовать несколько ядер, нам нужно найти способ разделить нашу работу на части, которые мы можем обрабатывать параллельно. Если бы это был не узел, мы бы использовали streamи для этого; 32 streamа, по одному для каждого ядра процессора. Однако, поскольку у нас есть Node, мы создадим 32 процесса Node.

Темы могут быть хорошей альтернативой процессам узлов, возможно, даже лучшим способом; но только в определенном виде работы, где работа уже определена, и мы полностью контролируем, как ее обрабатывать. Кроме этого, для любого другого рода проблемы, когда работа идет снаружи так, как мы не имеем контроля над и мы хотим, чтобы ответить как можно быстрее, путем Node является неоспоримо выше.

Эй, Хасан, ты все еще работаешь однопоточно? Что с тобой случилось, мужик? Я только что предоставил вам то, что вы хотели. У вас больше нет оправданий. Создавайте streamи, чтобы они работали быстрее.

– Я разделил произведение на части, и каждый процесс будет работать на одной из этих частей параллельно.

– Почему вы не создаете темы?

– Извините, я не думаю, что это можно использовать. Вы можете взять свой компьютер, если хотите?

– Ничего, я classный, я просто не понимаю, почему вы не используете streamи?

– Спасибо за компьютер. 🙂 Я уже разделил произведение на части, и я создаю процессы для работы над этими частями параллельно. Все процессорные ядра будут полностью использованы. Я мог бы сделать это с помощью streamов вместо процессов; но Узел так, и мой босс Парт Тхаккар хочет, чтобы я использовал Узел.

– Хорошо, дайте мне знать, нужен ли вам другой компьютер. :п

Если я создам 33 процесса, вместо 32, планировщик операционной системы будет приостанавливать stream, запускать другой, приостанавливать его после нескольких циклов, снова запускать другой … Это лишние накладные расходы. Я не хочу этого. Фактически, в системе с 32 ядрами я бы даже не хотел создавать ровно 32 процесса, 31 может быть приятнее . Потому что это не просто мое приложение, которое будет работать в этой системе. Оставить небольшую комнату для других вещей может быть хорошо, особенно если у нас есть 32 номера.

Я считаю, что сейчас мы на одной странице полностью используем процессоры для задач с интенсивным использованием ЦП .

– Хм, Хасан, мне очень жаль насмехаться над вами. Полагаю, теперь я понимаю тебя лучше. Но есть еще кое-что, что мне нужно для объяснения: что все жужжит для запуска сотен streamов? Я читаю везде, что streamи намного быстрее создают и тупые, чем процессы разветвления? Вы используете процессы fork вместо streamов, и вы думаете, что это самый высокий уровень, который вы получите с помощью Node. Тогда Node не подходит для такого рода работ?

– Не беспокойся, я тоже classный. Все говорят об этом, поэтому я думаю, что привык их слышать.

— Так? Узел не подходит для этого?

– Узел отлично подходит для этого, даже если streamи тоже хороши. Что касается накладных расходов на stream / процесс; на то, что вы повторяете много, каждая миллисекунда считается. Тем не менее, я создаю только 32 процесса, и потребуется немного времени. Это произойдет только один раз. Это не будет иметь никакого значения.

– Когда я хочу создать тысячи streamов, то?

– Вы никогда не хотите создавать тысячи streamов. Тем не менее, в системе, которая выполняет работу, которая поступает извне, например, веб-сервер, обрабатывающий HTTP-запросы; если вы используете stream для каждого запроса, вы будете создавать много streamов, многие из них.

– Узел другой, правда? Правильно?

— Да, точно. Именно здесь Node действительно сияет. Подобно streamу намного легче процесса, вызов функции намного легче, чем stream. Узел вызывает функции вместо создания streamов. В примере веб-сервера каждый входящий запрос вызывает вызов функции.

– Хм, интересно; но вы можете запускать только одну функцию одновременно, если вы не используете несколько streamов. Как это может работать, когда на веб-сервер поступает много запросов одновременно?

– Вы совершенно правы в том, как работают функции, по одному, а не два параллельно. Я имею в виду, что в одном процессе одновременно выполняется только одна область кода. Планировщик ОС не приходит и не приостанавливает эту функцию и переключается на другую, если она не приостанавливает процесс, чтобы дать время другому процессу, а не другой stream в нашем процессе. (2)

– Тогда как процесс обрабатывает 2 запроса одновременно?

– Процесс может обрабатывать десятки тысяч запросов за раз, пока наша система имеет достаточные ресурсы (оперативная память, сеть и т. Д.). Как работают эти функции, ОСНОВНАЯ РАЗЛИЧИЯ.

– Хм, мне теперь нужно возбуждать?

– Может быть 🙂 Узел запускает цикл по очереди. В этой очереди находятся наши задания, то есть вызовы, которые мы начали обрабатывать входящие запросы. Наиболее важным моментом здесь является то, как мы разрабатываем наши функции для запуска. Вместо того, чтобы начать обработку запроса и заставить вызывающего абонента ждать, пока мы закончим работу, мы быстро прекратим нашу функцию после выполнения приемлемого объема работы. Когда мы подошли к точке, где нам нужно подождать, пока другой компонент выполнит какую-то работу и вернет нам значение, вместо того, чтобы ждать этого, мы просто закончим нашу функцию, добавив остальную работу в очередь.

– Звучит слишком сложно?

– Нет, я мог бы казаться сложным; но сама система очень проста и имеет смысл.

Теперь я хочу прекратить ссылаться на диалог между этими двумя разработчиками и закончить свой ответ после последнего быстрого примера того, как эти функции работают.

Таким образом, мы делаем то, что обычно планировал Scheduler. В какой-то момент мы приостанавливаем нашу работу и позволяем запускать другие вызовы функций (например, другие streamи в многопоточной среде), пока мы не вернемся к нашей очереди. Это намного лучше, чем оставить работу OS Scheduler, которая пытается дать время для каждого streamа в системе. Мы знаем, что мы делаем намного лучше, чем OS Scheduler, и мы должны прекратить работу, когда мы должны остановиться.

Ниже приведен простой пример, когда мы открываем файл и читаем его, чтобы выполнить некоторую работу над данными.

Синхронный путь:

Open File Repeat This: Read Some Do the work 

Асинхронный путь:

 Open File and Do this when it is ready: // Our function returns Repeat this: Read Some and when it is ready: // Returns again Do some work 

Как видите, наша функция просит систему открыть файл и не дожидаться его открытия. Он заканчивается, предоставляя следующие шаги после того, как файл готов. Когда мы возвращаемся, Node выполняет другие вызовы функций в очереди. После запуска всех функций цикл события перемещается в следующий ход …

Таким образом, Узел имеет совершенно другую парадигму, чем многопоточная разработка; но это не означает, что ему не хватает вещей. Для синхронного задания (где мы можем решить порядок и способ обработки) он работает, а также многопоточный параллелизм. Для работы, которая приходит извне, как запросы на сервер, она просто превосходит.


(1) Если вы не создаете библиотеки на других языках, таких как C / C ++, в этом случае вы по-прежнему не создаете streamи для разделения заданий. Для такого рода работ у вас есть два streamа, один из которых продолжит общение с узлом, а другой – реальную работу.

(2) Фактически, каждый процесс узла имеет несколько streamов по тем же причинам, о которых я упомянул в первой сноске. Однако это не похоже на то, как 1000 streamов выполняют аналогичные работы. Эти дополнительные streamи предназначены для того, чтобы принимать события IO и обрабатывать обмен сообщениями между процессами.

ОБНОВЛЕНИЕ (Отвечая на хороший вопрос в комментариях)

@ Марк, спасибо за конструктивную критику. В парадигме узла у вас никогда не должно быть функций, которые занимают слишком много времени, пока все остальные вызовы в очереди не будут запущены один за другим. В случае дорогостоящих вычислительных задач, если мы посмотрим на картину в полном объеме, мы видим, что это не вопрос «Должны ли мы использовать streamи или процессы?» но вопрос «Как мы можем сбалансированно разделить эти задачи на подзадачи, чтобы мы могли их параллельно запускать, используя несколько процессоров в системе?» Скажем, мы будем обрабатывать 400 видеофайлов в системе с 8 ядрами. Если мы хотим обрабатывать один файл за раз, нам нужна система, которая будет обрабатывать разные части одного и того же файла, и в этом случае, возможно, многопоточная система с одним процессом будет легче создавать и даже более эффективно. Мы все еще можем использовать Node для этого, запуская несколько процессов и передавая сообщения между ними, когда требуется совместное использование / обмен данными. Как я уже говорил, многопроцессорный подход с узлом, а также многопоточный подход в таких задачах; но не более того. Опять же, как я уже говорил ранее, ситуация, при которой Node светит, заключается в том, что эти задачи поступают как входные данные в систему из нескольких источников, поскольку одновременное соединение многих соединений намного легче в узле по сравнению с streamом за соединение или процессом за соединение система.

Что касается вызовов setTimeout(...,0) ; иногда предоставляя перерыв во время трудоемкой задачи, чтобы позволить вызовам в очереди иметь свою долю обработки, может потребоваться. Разделение задач по-разному может спасти вас от них; но все же, это не хак, это просто то, как работают очереди событий. Кроме того, использование process.nextTick для этой цели намного лучше, поскольку, когда вы используете setTimeout , будет необходимо вычислить и проверить пройденное время, а process.nextTick – это просто то, что мы действительно хотим: «Эй, задача, вернуться к концу очереди , вы использовали свою долю! ”

(Обновление 2016: веб-работники входят в io.js – Node.js fork Node.js v7 – см. Ниже.)

(Обновление 2017: веб-работники не входят в Node.js v7 или v8 – см. Ниже.)

(Обновление 2018: веб-работники входят в Node.js Node v10.5.0 – см. Ниже.)

Некоторые разъяснения

Прочитав ответы выше, я хотел бы отметить, что в веб-работниках нет ничего, что противоречит философии JavaScript в целом и узлу, в частности, относительно параллелизма. (Если бы это было, это не было бы даже обсуждено WHATWG, а тем более реализовано в браузерах).

Вы можете думать о веб-работнике как о легком микросервисе, к которому обращаются асинхронно. Ни одно государство не используется. Никаких проблем с блокировкой не существует. Нет блокировки. Синхронизация не требуется. Точно так же, как при использовании службы RESTful из вашей программы Node, вы не беспокоитесь, что теперь она «многопоточна», потому что служба RESTful не находится в том же streamе, что и ваш собственный цикл событий. Это просто отдельная услуга, к которой вы обращаетесь асинхронно, и это важно.

То же самое с веб-работниками. Это просто API для связи с кодом, который работает в совершенно отдельном контексте и находится ли он в разных streamах, разных процессах, разных группах, зонах, контейнерах или разных машинах, совершенно не имеет значения из-за строго асинхронного, неблокирующего API, со всеми данными, переданными по значению.

На самом деле веб-работники концептуально идеально подходят для узла, который, как многие люди не знают, попутно использует streamи довольно сильно, а на самом деле «все работает параллельно, кроме вашего кода» – см .:

  • Понимание цикла событий node.js Микито Такада
  • Понимание node.js от Felix Geisendörfer
  • Понимание цикла событий Node.js от Trevor Norris
  • Сам Node.js блокирует, только его ввод-вывод не блокируется Джереми Эпштейном

Но веб-работников даже не нужно реализовывать с помощью streamов. Вы можете использовать процессы, зеленые streamи или даже службы RESTful в облаке – до тех пор, пока используется API веб-работников. Вся красота передающего сообщения API с помощью семантики вызова по значению заключается в том, что базовая реализация практически не имеет значения, поскольку детали модели параллелизма не будут отображаться.

Однопоточный цикл событий идеально подходит для операций с привязкой к вводу / выводу. Это не так хорошо работает для операций с ЦП, особенно для длинных. Для этого нам нужно создать больше процессов или использовать streamи. Управление дочерними процессами и взаимодействие между процессами переносимым образом может быть довольно сложным, и его часто считают излишним для простых задач, в то время как использование streamов означает работу с блокировками и проблемами синхронизации, которые очень трудно сделать правильно.

Часто рекомендуется разделять длительные операции с привязкой к ЦП на более мелкие задачи (что-то вроде примера в разделе «Оригинальный ответ» моего ответа на Ускорение setInterval ), но это не всегда практично, и оно не использует больше чем одно kernel ​​ЦП.

Я пишу это, чтобы уточнить комментарии, которые в основном говорят о том, что веб-рабочие были созданы для браузеров, а не для серверов (забывая, что это можно сказать о многом в JavaScript).

Узел модhive

Существует несколько модhive, которые должны добавить веб-работников в узел:

Я не использовал ни одного из них, но у меня есть два быстрых наблюдения, которые могут иметь значение: по состоянию на март 2015 года узел-webworker был последний раз обновлен 4 года назад, а thread-webworker-threads был обновлен месяц назад. Также я вижу в примере использования узлов-webworker-streamов, что вы можете использовать функцию вместо имени файла в качестве аргумента для конструктора Worker, который, похоже, может вызвать тонкие проблемы, если он реализован с использованием streamов, которые обмениваются памятью (если только функции используются только для своего метода .toString () и в других случаях скомпилированы в другой среде, и в этом случае это может быть хорошо – мне нужно глубже вникать в это, просто поделившись своими наблюдениями здесь).

Если есть какой-либо другой соответствующий проект, который реализует API веб-рабочих в узле, оставьте комментарий.

Обновление 1

Я еще не знал этого на момент написания, но, кстати, за один день до того, как я написал этот ответ, веб-работники были добавлены в io.js.

( io.js является fork of Node.js – см .: Почему io.js решила fork Node.js , интервью InfoWorld с Майкелем Роджерсом, для получения дополнительной информации.)

Это не только доказывает, что в веб-работниках нет ничего, что противоречит философии JavaScript в целом и узлу в частности в отношении параллелизма, но это может привести к тому, что веб-работники станут гражданами первого classа на серверном JavaScript, таком как io. js (и, возможно, Node.js в будущем), так же, как и в клиентском JavaScript во всех современных браузерах .

Обновление 2

В обновлении 1 и моем твитте я имел в виду запрос на удаление ia.js № 1159, который теперь перенаправляется на Node PR # 1159, который был закрыт 8 июля и заменен на Node PR # 2133 – который все еще открыт. Существует некоторая дискуссия, проходящая под этими запросами на растяжение, которые могут предоставить более подробную информацию о статусе веб-работников в io.js / Node.js.

Обновление 3

Последняя информация – благодаря NiCk Newman для публикации его в комментариях: Есть работники: первоначальная реализация фиксируется Петкой Антоновым с 6 сентября 2015 года, которую можно загрузить и опробовать в этом дереве . Подробнее см. Комментарии NiCk Newman .

Обновление 4

По состоянию на май 2016 года последние комментарии по прежнему открытым PR # 2133 – работникам: первоначальная реализация была 3 месяца. 30 мая Matheus Moreira попросил меня опубликовать обновление для этого ответа в комментариях ниже, и он попросил указать текущий статус этой функции в комментариях к PR.

Первые ответы в PR-дискуссии были скептичны, но позже Бен Ноордхуис писал, что «объединение этого в той или иной форме происходит в моем списке дел для v7».

Все остальные комментарии, похоже, были вторыми, и, по состоянию на июль 2016 года, кажется, что веб-рабочие должны быть доступны в следующей версии Node , версия 7.0, которая планируется выпустить в октябре 2016 года (не обязательно в форме этого точного PR).

Спасибо Matheus Moreira за то, что он указал на комментарии и оживил обсуждение GitHub.

Обновление 5

По состоянию на июль 2016 года на npm было мало модhive, которые раньше не были доступны – для получения полного списка соответствующих модhive, поиска npm для рабочих, веб-работников и т. Д. Если что-то в особенности работает или не работает для вас, отправьте сообщение комментарий.

Обновление 6

По состоянию на январь 2017 года вряд ли веб-работники будут объединены в Node.js.

Потребительский запрос № 2133 : первоначальная реализация Петкой Антоновым с 8 июля 2015 года была окончательно закрыта Беном Ноордхусом 11 декабря 2016 года, который прокомментировал, что «поддержка многопоточности добавляет слишком много новых отказов для недостаточной выгоды» и «мы также может сделать это с использованием более традиционных средств, таких как разделяемая память и более эффективная сериализация ».

Для получения дополнительной информации см. Комментарии к PR 2133 на GitHub.

Еще раз спасибо Matheus Moreira за то, что он указал на комментарии.

Обновление 6

Я рад сообщить, что несколько дней назад в июне 2018 года веб-работники появились в Node v10.5.0 в качестве экспериментальной функции, активированной --experimental-worker .

Для получения дополнительной информации см .:

  • Выпуск блога Node v10.5.0
  • Pull Request # 20876 – работник: первоначальная реализация Анны Хеннингсен
  • Мое первоначальное твист счастья, когда я узнал, что это попало в v10.5.0:

🎉🎉🎉 Наконец! Я могу сделать 7-е обновление для моего 3-летнего ответа на переполнение стека, в котором я утверждаю, что streamи рабочих веб-страниц не противоречат философии узла, только на этот раз, говоря, что мы наконец получили это! 😜👍

Я пришел из старой школы мысли, где мы использовали multithreading, чтобы быстро сделать программное обеспечение. За последние 3 года я использую Node.js и большой сторонник этого. Как подробно объяснил, как работает узел, и концепция асинхронной функциональности. Но позвольте мне добавить несколько вещей здесь.

Вернувшись в старые времена с одиночными ядрами и более низкими тактовыми частотами, мы пробовали различные способы сделать работу программного обеспечения быстрой и параллельной. в DOS дней мы используем для запуска по одной программе за раз. В windowsх мы запускали несколько приложений (процессов) вместе. Концепции, такие как упреждающие и не превентивные (или совместные), где протестированы. теперь мы знаем, что превентивный ответ был ответом на лучшую задачу многопроцессорности на одноядерных компьютерах. Наряду с концепциями процессов / задач и переключения контекста. Чем концепция streamа для дальнейшего снижения нагрузки на переключение контекста процесса. Поток, который придумал как легкий вес, альтернативный нерестам новых процессов.

Так что нравится или нет сигнальный stream или не многоядерный или одноядерный, ваши процессы будут выгружены ОС и вырезаны по времени.

Nodejs – это единственный процесс и обеспечивает механизм async. Здесь рабочие места отправляются под управлением ОС для выполнения задач, пока мы ожидаем в цикле событий для завершения задачи. Как только мы получим зеленый сигнал от ОС, мы выполняем все, что нам нужно. Теперь в некотором роде это совместная / неперехваченная многозадачность, поэтому мы никогда не должны блокировать цикл событий в течение очень длительного периода времени. Другими словами, мы очень быстро разрушаем наше приложение.
Поэтому, если есть когда-либо задача, которая блокирует природу или очень трудоемка, нам придется разветвить ее на превентивный мир ОС и streamов. есть хорошие примеры этого в документации libuv . Кроме того, если вы прочитаете документацию, вы обнаружите, что FileI / O обрабатывается в streamах в node.js.

Итак, во-первых, все это в дизайне нашего программного обеспечения. Во-вторых, контекстное переключение всегда происходит независимо от того, что они говорят вам. Тема там и все еще существует по какой-то причине, причина в том, что они быстрее переключаются между процессами.

Под капотом в node.js все его c ++ и streamи. И узел обеспечивает c ++ способ расширить свою функциональность и ускорить работу, используя streamи, где они являются обязательными, то есть блокирование таких задач, как чтение из источника записи в источник, большой анализ данных и т. Д.

Я знаю, что ответ hasanyasin является принятым, но для меня streamи будут существовать независимо от того, что вы говорите, или как вы скрываете их за скриптами, во-вторых, никто не просто ломает вещи в streamи только для скорости, в основном это делается для блокировки задач. И нити находятся в задней части Node.js, поэтому, прежде чем полностью избивать multithreading, это правильно. Кроме того, streamи отличаются от процессов, и ограничение наличия процессов узла на kernel ​​не совсем относится к числу streamов, streamи как subprocessы относятся к процессу. на самом деле нитки выиграли, т отображаются в диспетчере задач Windows или в верхней команде linux. в очередной раз они имеют меньший вес, чем процессы

Я не уверен, что в этом случае важны веб-работники, они являются технологиями на стороне клиента (запускаются в браузере), а node.js работает на сервере. Волwindows, насколько я понимаю, также блокируют, т. Е. Являются добровольной многозадачностью, поэтому вы можете их использовать, но должны управлять контекстами, переключающимися самим собой через yield . Темы могут быть на самом деле то, что вам нужно, но я не знаю, насколько они зрелы в node.js.

worker_threads был реализован и отправлен за флаг в [email protected] . Это по-прежнему первоначальная реализация, и для повышения ее эффективности в будущих выпусках необходимы дополнительные усилия. Стоит дать ему попробовать в последнем node .

По мнению многих разработчиков Node, одна из лучших частей узла – это однопоточный характер. Нити представляют собой множество трудностей с общими ресурсами, которые Node полностью избегает, не делая ничего, кроме неблокирующего ввода-вывода.

Это не означает, что узел ограничен одним streamом. Просто метод получения многопоточного параллелизма отличается от того, что вы ищете. Стандартный способ борьбы с streamами состоит в том, что модуль кластера входит в стандартную комплектацию с самим узлом. Это более простой подход к streamам, чем ручное обращение с ними в вашем коде.

Для работы с асинхронным программированием в вашем коде (как и во избежание вложенных пирамид обратного вызова), компонент [Future] в библиотеке Fibers является достойным выбором. Я также предлагаю вам проверить Asyncblock, который основан на Fibers. Волwindows хороши, потому что они позволяют скрыть обратный вызов, дублируя стек, а затем перепрыгивая между стеками по одному streamу по мере необходимости. Экономит вас от настоящих streamов, предоставляя вам преимущества. Недостатком является то, что трассировки стека могут быть немного странными при использовании Fibers, но они не так уж плохи.

Если вам не нужно беспокоиться о асинхронном материале и больше заинтересованы в том, чтобы делать большую обработку без блокировки, вам просто нужен простой вызов process.nextTick (обратный вызов) каждый раз в то время.

Может быть, дополнительная информация о том, какие задачи вы выполняете, поможет. Зачем вам (как вы упомянули в своем комментарии к ответу genericdave) нужно создать много тысяч из них? Обычный способ сделать это в узле – это запустить рабочий процесс (используя fork или какой-либо другой метод), который всегда запускается и может быть передан при использовании сообщений. Другими словами, не запускайте нового работника каждый раз, когда вам нужно выполнять любую задачу, которую вы выполняете, но просто отправляйте сообщение уже запущенному работнику и получите ответ, когда это будет сделано. Честно говоря, я не вижу, что запуск многих тысяч реальных streamов будет очень эффективным, вы все еще ограничены вашими процессорами.

Теперь, сказав все это, я много работал с Hook.io в последнее время, который, похоже, очень хорошо работает для таких задач по загрузке в другие процессы, может быть, он может выполнить то, что вам нужно.

  • Почему мы не можем использовать dispatch_sync в текущей очереди?
  • Какой stream запускает код после ключевого слова `await`?
  • Проблемы с добавлением JTextArea
  • Как бы вы реализовали свой собственный механизм чтения / записи в C ++ 11?
  • Где я могу получить streamобезопасный CollectionView?
  • Продолжение задачи в streamе пользовательского интерфейса
  • Автоматизация кода кода InvokeRequired
  • ConfigureAwait подталкивает продолжение в stream пула
  • Почему бы не начать нить в конструкторе? Как прекратить?
  • В чем разница между Thread.start () и Thread.run ()?
  • Можно ли заставить существующее приложение Java использовать не более x ядер?
  • Давайте будем гением компьютера.