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

2023-11-27

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

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

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

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

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

Thanks


要了解这里发生的情况,您必须了解有关节点事件循环以及操作系统和 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,但操作系统仍然会决定插入其他内容。

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

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

希望能回答您的问题:D

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐