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)时,CPU使用率将达到100%或接近。问题是想象我在一台带有一个CPU的机器上运行,并且还有另一个节点HTTP服务器工作的过程,它对它有何影响?
Does the thread doing recursive process.nexttick let the HTTP server work at all?
线程是否正在进行递归process.nexttick让HTTP服务器工作?
If we have two threads of recursive process.nexttick, do they both get 50% share?
如果我们有两个递归process.nexttick的线程,他们都获得50%的份额?
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.
由于我不知道任何一个核心的机器都无法尝试。而且由于我对线程之间CPU的时间共享的理解在这种情况下是有限的,所以我不应该如何尝试使用具有4核CPU的机器。
function interval(){
process.nextTick(function(){
someSmallSyncCode();
interval();
})
}
Thanks
2 个解决方案
#1
13
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.
要了解这里发生的事情,您必须了解有关节点的事件循环以及操作系统和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 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.
process.nextTick将一个函数作为一个回调函数,并将它放在事件循环下一次复制时要完成的事情列表中。然后执行此回调,完成后,再次注册相同的回调。本质上,这个和真正的递归之间的关键区别在于我们的调用堆栈永远不会有多个调用深度。我们永远不会“放松”堆栈,我们只是连续有很多小的短筹码。
Okay, so why does this matter?
好的,为什么这很重要?
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
当我们更好地理解事件循环以及真正发生的事情时,我们可以更好地理解系统资源的使用方式。通过以这种方式使用process.nextTick,您可以确保在事件循环中始终可以执行某些操作,这就是您获得高CPU使用率的原因(但您已经知道了)。现在,如果我们假设你的HTTP服务器作为脚本在SAME进程中运行,如下所示
function interval(){
process.nextTick(doIntervalStuff)
}
function doIntervalStuff() {
someSmallSyncCode();
interval();
}
http.createServer(function (req, res) {
doHTTPStuff()
}).listen(1337, "127.0.0.1");
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.
那么CPU使用情况如何在程序的两个不同部分之间分开?那很难说,但如果我们理解事件循环,我们至少可以猜测。
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.
由于我们使用process.nextTick,每次在事件循环的“开始”都会运行doIntervalStuff函数,但是,如果要为HTTP服务器做些什么(比如处理连接),那么我们知道会得到在下一次事件循环开始之前完成,并记住,由于节点的事件性质,这可以在事件循环的一次迭代中处理任意数量的连接。这意味着,至少在理论上,流程中的每个函数都获得了CPU使用所需的“需求”,然后process.nextTick函数使用其余函数。虽然这不完全正确(例如,你的一些阻塞代码会弄乱这个),但这是一个值得考虑的好模型。
Okay now (finally) on to your real question, what about separate processes?
好的,现在(最后)回答你真正的问题,那么单独的流程呢?
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.
有趣的是,操作系统和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.
因此,当您的节点进程表示它占用100%的cpu时,这是不准确的,否则,没有其他任何东西可以完成,系统会崩溃。从本质上讲,它可以占用所有CPU,但操作系统仍然可以确定其他内容。
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的第二个节点进程,操作系统将尝试适应这两个进程,并且根据每个节点进程的事件循环要完成的工作量,操作系统会分割工作因此(至少在理论上,但实际上可能只会导致一切变慢和系统不稳定)。
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.
再次,这是非常简单的,但希望它能让您了解正在发生的事情。话虽这么说,我不建议使用process.nextTick,除非你知道你需要它,如果每隔5毫秒做一件事是可以接受的,使用setTimeout代替process.nextTick将节省大量的cpu使用。
Hope that answers your question :D
希望能回答你的问题:D
#2
1
No. You don't have to artificially pause your processes to let others do their work, your operating system has mechanisms for that. In fact, using process.nextTick
in this way will slow your computer down because it has a lot of overhead.
不需要。您不必人为地暂停您的流程以让其他人完成工作,您的操作系统就有这样的机制。实际上,以这种方式使用process.nextTick会降低计算机速度,因为它有很多开销。
#1
13
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.
要了解这里发生的事情,您必须了解有关节点的事件循环以及操作系统和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 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.
process.nextTick将一个函数作为一个回调函数,并将它放在事件循环下一次复制时要完成的事情列表中。然后执行此回调,完成后,再次注册相同的回调。本质上,这个和真正的递归之间的关键区别在于我们的调用堆栈永远不会有多个调用深度。我们永远不会“放松”堆栈,我们只是连续有很多小的短筹码。
Okay, so why does this matter?
好的,为什么这很重要?
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
当我们更好地理解事件循环以及真正发生的事情时,我们可以更好地理解系统资源的使用方式。通过以这种方式使用process.nextTick,您可以确保在事件循环中始终可以执行某些操作,这就是您获得高CPU使用率的原因(但您已经知道了)。现在,如果我们假设你的HTTP服务器作为脚本在SAME进程中运行,如下所示
function interval(){
process.nextTick(doIntervalStuff)
}
function doIntervalStuff() {
someSmallSyncCode();
interval();
}
http.createServer(function (req, res) {
doHTTPStuff()
}).listen(1337, "127.0.0.1");
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.
那么CPU使用情况如何在程序的两个不同部分之间分开?那很难说,但如果我们理解事件循环,我们至少可以猜测。
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.
由于我们使用process.nextTick,每次在事件循环的“开始”都会运行doIntervalStuff函数,但是,如果要为HTTP服务器做些什么(比如处理连接),那么我们知道会得到在下一次事件循环开始之前完成,并记住,由于节点的事件性质,这可以在事件循环的一次迭代中处理任意数量的连接。这意味着,至少在理论上,流程中的每个函数都获得了CPU使用所需的“需求”,然后process.nextTick函数使用其余函数。虽然这不完全正确(例如,你的一些阻塞代码会弄乱这个),但这是一个值得考虑的好模型。
Okay now (finally) on to your real question, what about separate processes?
好的,现在(最后)回答你真正的问题,那么单独的流程呢?
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.
有趣的是,操作系统和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.
因此,当您的节点进程表示它占用100%的cpu时,这是不准确的,否则,没有其他任何东西可以完成,系统会崩溃。从本质上讲,它可以占用所有CPU,但操作系统仍然可以确定其他内容。
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的第二个节点进程,操作系统将尝试适应这两个进程,并且根据每个节点进程的事件循环要完成的工作量,操作系统会分割工作因此(至少在理论上,但实际上可能只会导致一切变慢和系统不稳定)。
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.
再次,这是非常简单的,但希望它能让您了解正在发生的事情。话虽这么说,我不建议使用process.nextTick,除非你知道你需要它,如果每隔5毫秒做一件事是可以接受的,使用setTimeout代替process.nextTick将节省大量的cpu使用。
Hope that answers your question :D
希望能回答你的问题:D
#2
1
No. You don't have to artificially pause your processes to let others do their work, your operating system has mechanisms for that. In fact, using process.nextTick
in this way will slow your computer down because it has a lot of overhead.
不需要。您不必人为地暂停您的流程以让其他人完成工作,您的操作系统就有这样的机制。实际上,以这种方式使用process.nextTick会降低计算机速度,因为它有很多开销。