Позволяет ли использование recursive process.nexttick другим процессам или потокам работать? - PullRequest
5 голосов
/ 13 ноября 2011

Технически, когда мы выполняем следующий код (recursive process.nexttick), загрузка ЦП достигает 100% или почти.Вопрос в том, что я работаю на машине с одним ЦП, и есть еще один процесс работы HTTP-сервера узла, как это влияет на него?

Позволяет ли поток, выполняющий рекурсивный процесс.nexttick, вообще работать HTTP-сервер?

Если у нас есть два потока рекурсивного процесса.nexttick, получают ли они оба 50% доли?

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

function interval(){
  process.nextTick(function(){
    someSmallSyncCode();
    interval();  
  })
} 

Спасибо

Ответы [ 2 ]

13 голосов
/ 13 ноября 2011

Чтобы понять, что здесь происходит, вы должны понять несколько вещей о цикле событий узла, а также об ОС и ЦП.

Прежде всего, давайте лучше разберем этот код.Вы называете это рекурсивным, но так ли это?

В рекурсии мы обычно думаем о вложенных стеках вызовов, а затем, когда вычисления выполнены (достигают базового случая), стек "раскручивается" обратно к точке, где нашбыла вызвана рекурсивная функция.

Хотя этот метод вызывает сам себя (косвенно через обратный вызов), цикл событий искажает то, что происходит на самом деле.

process.nextTick принимает функцию какобратный вызов и ставит его первым в списке вещей, которые будут сделаны на следующем цикле обработки событий.Затем выполняется этот обратный вызов, и когда он завершается, вы снова регистрируете тот же самый обратный вызов.По сути, ключевое различие между этой и настоящей рекурсией заключается в том, что наш стек вызовов никогда не получает более одного глубокого вызова.Мы никогда не «раскручиваем» стек, у нас просто есть множество маленьких коротких стеков подряд.

Хорошо, так почему это важно?

Когда мы лучше понимаем цикл событий и то, что на самом деле происходит, мы можем лучше понять, как используются системные ресурсы.Используя process.nextTick таким образом, вы гарантируете, что ВСЕГДА что-то нужно делать в цикле обработки событий, поэтому вы получаете высокую загрузку ЦП (но вы уже знали об этом).Теперь, если предположить, что ваш HTTP-сервер должен запускаться в одном и том же процессе в качестве сценария, как показано ниже

function interval(){
  process.nextTick(doIntervalStuff) 
}

function doIntervalStuff() {
  someSmallSyncCode();
  interval();
}

http.createServer(function (req, res) {
 doHTTPStuff()
}).listen(1337, "127.0.0.1");

, то как разделить использование ЦП между двумя разными частямипрограмма?Ну, это сложно сказать, но если мы понимаем цикл событий, мы можем, по крайней мере, догадаться.

Поскольку мы используем process.nextTick, функция doIntervalStuff будет запускаться каждый раз при «запуске» цикла событийоднако, если что-то нужно сделать для HTTP-сервера (например, обработать соединение), то мы знаем, что это будет сделано до следующего запуска цикла событий, и помним, что из-за четного характера узла это может бытьобработка любого количества соединений на одной итерации цикла событий.Это подразумевает, что, по крайней мере, теоретически каждая функция в процессе получает то, что ей «нужно» в части использования ЦП, а затем функции process.nextTick используют остальное.Хотя это не совсем верно (например, ваш кусочек блокирующего кода может испортить это), это достаточно хорошая модель, чтобы подумать.

Хорошо, теперь (наконец-то) к вашему реальному вопросу, чтопро отдельные процессы?

Интересно, что ОС и ЦП часто бывают очень «равномерными» по своей природе.Всякий раз, когда процесс хочет что-то сделать (например, в случае узла, запустить итерацию цикла событий), он делает запрос к обрабатываемой ОС, ОС затем помещает это задание в готовую очередь (которая имеет приоритет)и он выполняется, когда планировщик ЦП решает обойти его.Это опять-таки упрощенная модель, но основная концепция, которую нужно убрать, очень похожа на цикл обработки событий узла, каждый процесс получает то, что ему «нужно», а затем такой процесс, как приложение вашего узла, пытается выполнить, когда это возможно, заполняяпромежутки.

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

Если бы вы добавили процесс второго узла, который выполнял тот же процесс.nextTick, ОС постаралась бы приспособитьсяоба процесса и, в зависимости от объема работы, выполняемой в цикле обработки событий каждого узла, ОС будет соответствующим образом разделять работу (по крайней мере, теоретически, но в действительности, вероятно, просто приведет к замедлению всего и нестабильности системы).

Еще раз, это очень упрощенно, но, надеюсь, это даст вам представление о том, что происходит.Тем не менее, я бы не рекомендовал использовать process.nextTick, если вы не знаете, что он вам нужен, если делать что-то каждые 5 мс приемлемо, используя setTimeout вместо process.nextTick сэкономит кучу ресурсов при использовании процессора.

Надеюсь, что ответит на ваш вопрос: D

1 голос
/ 13 ноября 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...