使用递归 process.nexttick 是否可以让其他进程或线程工作?

发布于 2024-12-14 23:42:01 字数 477 浏览 2 评论 0原文

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

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

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

由于我不知道任何具有一个核心的机器无法尝试。由于我对线程之间 CPU 时间共享的理解在这种情况下是有限的,所以我不知道应该如何在具有 4 核 CPU 的机器上尝试它。

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

谢谢

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?

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

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

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();  
  })
} 

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

筑梦 2024-12-21 23:42:01

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

首先,让我们更好地理解这段代码。你称这为递归,但真的是这样吗?

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

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

process.nextTick 将一个函数作为回调,并将其放在事件循环的下一次循环中要完成的任务列表中的第一个位置。然后执行该回调,完成后,您再次注册相同的回调。从本质上讲,这种递归与真正的递归之间的主要区别在于,我们的调用堆栈永远不会超过一次调用深度。我们从不“展开”筹码堆,我们只是连续拥有许多小的短筹码堆。

好吧,那为什么这很重要呢?

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

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

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

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

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

由于我们使用 process.nextTick,因此 doIntervalStuff 函数将在每次事件循环“开始”时运行,但是,如果需要为 HTTP 服务器执行某些操作(例如处理连接),那么我们知道将会得到在下一次事件循环开始之前完成,并记住,由于节点的事件性质,这可能会在事件循环的一次迭代中处理任意数量的连接。这意味着,至少在理论上,进程中的每个函数都会获得它“需要”的 CPU 使用率,然后 process.nextTick 函数使用其余的。虽然这并不完全正确(例如,您的一些阻塞代码会将其搞砸),但它是一个足够好的模型值得考虑。

好吧,现在(最后)谈谈你真正的问题,单独的流程怎么样?

有趣的是,操作系统和 CPU 本质上通常也非常“事件”。每当一个进程想要做某事时(例如在节点的情况下,启动事件循环的迭代),它会向操作系统发出要处理的请求,然后操作系统将该作业推入就绪队列(按优先级排列)当 CPU 调度程序决定抽出时间来处理它时,它就会执行。这又是一个过于简化的模型,但要带走的核心概念是,就像在节点的事件循环中一样,每个进程都会获得它“需要”的内容,然后像节点应用程序这样的进程会尝试通过填写差距。

因此,当你的节点进程说它占用了 100% 的 cpu 时,这是不准确的,否则,其他任何事情都不会完成,系统也会崩溃。从本质上讲,它会占用所有可以使用的 CPU,但操作系统仍然会确定要插入的其他内容。

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

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

希望能回答您的问题:D

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 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?

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");

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.

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?

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.

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.

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).

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.

Hope that answers your question :D

孤独患者 2024-12-21 23:42:01

不。您不必人为地暂停进程来让其他人完成他们的工作,您的操作系统有相应的机制。事实上,以这种方式使用 process.nextTick 会降低计算机的速度,因为它会产生大量开销。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文