【问题标题】:Does use of recursive process.nexttick let other processes or threads work?使用递归 process.nexttick 是否让其他进程或线程工作?
【发布时间】:2011-12-28 02:00:38
【问题描述】:

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

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

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

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

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

谢谢

【问题讨论】:

  • 节点没有线程。您是在谈论完全独立的进程或在同一个节点实例中发生的事情吗?
  • 不,我说的是节点的两个独立进程,不是同一个实例。
  • 已编辑,将线程更改为进程。

标签: node.js process multiprocessing cpu-usage


【解决方案1】:

要了解这里发生了什么,您必须了解有关节点的事件循环以及操作系统和 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

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 如果我们有两个递归 process.nexttick 线程,它们是否都获得了 50% 的份额?
    • @alFReDNSH:关于调用,但不是时间。
    猜你喜欢
    • 1970-01-01
    • 2012-07-02
    • 1970-01-01
    • 1970-01-01
    • 2017-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多