使用递归 process.nexttick 是否让其他进程或线程工作? [英] Does use of recursive process.nexttick let other processes or threads work?

查看:24
本文介绍了使用递归 process.nexttick 是否让其他进程或线程工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从技术上讲,当我们执行以下代码(recursive process.nexttick)时,CPU 使用率将达到 100% 或接近.问题是想象我在一台有一个 CPU 的机器上运行,并且有另一个节点 HTTP 服务器进程在工作,它是如何影响它的?

Technically when we execute the following code(recursive process.nexttick), the CPU usage would get to 100% or near. The question is the imagining that I'm running on a machine with one CPU and there's another process of node HTTP server working, how does it affect it?

执行递归 process.nexttick 的线程是否让 HTTP 服务器工作?

Does the thread doing recursive process.nexttick let the HTTP server work at all?

如果我们有两个递归 process.nexttick 线程,它们是否都获得了 50% 的份额?

If we have two threads of recursive process.nexttick, do they both get 50% share?

由于我不知道任何一台单核机器都不能尝试.而且由于我对这种情况下线程之间的 CPU 时间共享的理解有限,所以我不应该在具有 4 核 CPU 的机器上尝试它.

Since I don't know any machine with one core cannot try it. And since my understanding of time sharing of the CPU between threads is limited in this case, I don't how should try it with machines that have 4 cores of CPU.

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

谢谢

推荐答案

要了解这里发生了什么,您必须了解有关节点的事件循环以及操作系统和 CPU 的一些事情.

To understand whats going on here, you have to understand a few things about node's event loop as well as the OS and CPU.

首先,让我们更好地理解这段代码.你称之为递归,但它是吗?

First of all, lets understand this code better. You call this recursive, but is it?

在递归中,我们通常会想到嵌套调用堆栈,然后当计算完成时(达到基本情况),堆栈展开"回到调用递归函数的位置.

In recursion we normally think of nested call stacks and then when the computation is done (reaching a base case), the stack "unwinds" back to the point of where our recursive function was called.

虽然这是一个调用自身的方法(间接通过回调),但事件循环会扭曲实际发生的情况.

While this is a method that calls itself (indirectly through a callback), the event loop skews what is actually going on.

process.nextTick 将一个函数作为回调,并将其放在事件循环下一次复飞时要完成的任务列表的首位.然后执行此回调,完成后,您再次注册相同的回调.从本质上讲,这与真正的递归之间的关键区别在于,我们的调用堆栈永远不会超过一个调用深度.我们从不展开"筹码,我们只是有很多连续的小筹码.

process.nextTick takes a function as a callback and puts it first at the list of stuff to be done on the next go-around of the event loop. This callback is then executed and when it is done, you once again register the same callback. Essentially, the key difference between this and true recursion is that our call stack never gets more than one call deep. We never "unwind" the stack, we just have lots of small short stacks in succession.

好的,为什么这很重要?

Okay, so why does this matter?

当我们更好地了解事件循环以及真正发生的事情时,我们可以更好地了解系统资源是如何使用的.通过以这种方式使用 process.nextTick,您可以确保在事件循环中总是有一些事情要做,这就是您获得高 CPU 使用率的原因(但您已经知道了).现在,如果我们假设您的 HTTP 服务器将在与脚本相同的进程中运行,如下所示

When we understand the event loop better and what is really going on, we can better understand how system resources are used. By using process.nextTick in this fashion, you are assuring there is ALWAYS something to do on the event loop, which is why you get high cpu usage (but you knew that already). Now, if we were to suppose that your HTTP server were to run in the SAME process as the script, such as below

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

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

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

那么 CPU 使用率是如何在程序的两个不同部分之间分配的呢?好吧,这很难说,但如果我们了解事件循环,我们至少可以猜到.

then how does the CPU usage get split up between the two different parts of the program? Well thats hard to say, but if we understand the event loop, we can at least guess.

由于我们使用了 process.nextTick,所以 doIntervalStuff 函数将在每次事件循环的开始"处运行,但是,如果对 HTTP 服务器有一些事情要做(比如处理连接),那么我们知道这将在下一次事件循环开始之前完成,请记住,由于节点的事件性质,这可以在事件循环的一次迭代中处理任意数量的连接.这意味着,至少在理论上,进程中的每个函数都会得到它需要"的 CPU 使用率,然后 process.nextTick 函数使用其余的.虽然这并不完全正确(例如,你的一些阻塞代码会搞砸这个),但它是一个足够好的模型来考虑.

Since we use process.nextTick, the doIntervalStuff function will be run every time at the "start" of the event loop, however, if there is something to be done for the HTTP server (like handle a connection) then we know that will get done before the next time the event loop starts, and remember, due to the evented nature of node, this could be handling any number of connections on one iteration of the event loop. What this implies, is that at least in theory, each function in the process gets what it "needs" as far as CPU usage, and then the process.nextTick functions uses the rest. While this isn't exactly true (for example, your bit of blocking code would mess this up), it is a good enough model to think about.

好的,现在(最后)回答您真正的问题,单独的流程呢?

Okay now (finally) on to your real question, what about separate processes?

有趣的是,操作系统和 CPU 通常在本质上也是非常事件"的.每当一个进程想要做某事时(比如在节点的情况下,开始事件循环的迭代),它都会向操作系统发出请求以进行处理,然后操作系统将这个作业推入就绪队列(优先)它在 CPU 调度程序决定绕过它时执行.这又是一个过于简化的模型,但要带走的核心概念就像在节点的事件循环中一样,每个进程都得到它需要"的东西,然后像你的节点应用程序这样的进程通过填写差距.

Interestingly enough, the OS and CPU are often times also very "evented" in nature. Whenever a processes wants to do something (like in the case of node, start an iteration of the event loop), it makes a request to the OS to be handled, the OS then shoves this job in a ready queue (which is prioritized) and it executes when the CPU scheduler decides to get around to it. This is once again is an oversimplified model, but the core concept to take away is that much like in node's event loop, each process gets what it "needs" and then a process like your node app tries to execute whenever possible by filling in the gaps.

因此,当您的节点进程说它占用了 100% 的 cpu 时,这是不准确的,否则,其他任何事情都不会完成并且系统会崩溃.从本质上讲,它占用了它所能占用的所有 CPU,但操作系统仍然决定要加入其他东西.

So when your node processes says its taking 100% of cpu, that isn't accurate, otherwise, nothing else would ever be getting done and the system would crash. Essentially, its taking up all the CPU it can but the OS still determines other stuff to slip in.

如果您要添加执行相同 process.nextTick 的第二个节点进程,操作系统会尝试同时容纳这两个进程,并且根据每个节点进程的事件循环上要完成的工作量,操作系统会分裂相应地提高工作(至少在理论上,但实际上可能只会导致一切变慢和系统不稳定).

If you were to add a second node process that did the same process.nextTick, the OS would try to accommodate both processes and, depending on the amount of work to be done on each node process's event loop, the OS would split up the work accordingly (at least in theory, but in reality would probably just lead to everything slowing down and system instability).

再一次,这过于简单化了,但希望它能让您了解正在发生的事情.话虽如此,除非您知道自己需要它,否则我不建议使用 process.nextTick,如果可以接受每 5 毫秒执行一次操作,那么使用 setTimeout 而不是 process.nextTick 将节省大量 CPU 使用率.

Once again, this is very oversimplified, but hopefully it gives you an idea of what is going on. That being said, I wouldn't recommend using process.nextTick unless you know you need it, if doing something every 5 ms is acceptable, using a setTimeout instead of process.nextTick will save oodles on cpu usage.

希望能回答你的问题:D

Hope that answers your question :D

这篇关于使用递归 process.nexttick 是否让其他进程或线程工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆