NextTick() 不起作用 [将 CPU 密集型任务与其他事件交错]

NextTick() does not working [Interleaving CPU-intensive task with other events]

本文关键字:其他 事件 任务 密集型 不起作用 CPU NextTick      更新时间:2023-09-26

我在读 http://howtonode.org/understanding-process-next-tick但是,它附带的代码不会实现 CPU 密集型任务。

我试图写我的版本。但这是错误的。

执行

compute() 后,没有任何 IO 提供服务。

所以,我的问题是:在这种情况下使用 nextTick() 函数的正确方法是什么?

我不想在执行 compute() 时阻止 IO。

var http = require('http');
function compute() {
    // performs complicated calculations continuously
    // ...
    var result = 0;
    for(var i = 0; i < 1000000; i++){
        for(var j = i;  j < 1000000; j++){
            result += i + j;
        }
    }
    process.nextTick(compute);
}
http.createServer(function(req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World');
}).listen(5000, '127.0.0.1');

compute();

nextTick只是安排在事件循环的下一个时钟周期调用您的函数。 它不会赋予该功能神奇的无阻塞特性;JavaScript仍然是单线程的。 如果功能块(通过执行大量 CPU 密集型工作),它仍会导致 I/O 事件排队,直到函数完成。

如果需要执行 CPU 密集型工作,请在工作进程中执行。

nextTick 是一个阻塞调用(至少在节点 v0.10.29 中,我在那里测试了这个),它可以阻止其他事件运行。 使用 setImmediate()

>setImmediate会更好地工作,正如我的博客文章 setTimeout 和 Friends 中所解释的那样,因为它将允许 IO 任务在再次锁定主执行线程之前运行完整的compute。但正如发布的其他答案所暗示的那样,思考这个问题的方式不是"nextTick不起作用",而是"哎呀,我正在尝试做你绝对不能在节点.js应用程序中做的唯一事情之一,我得到了我被警告的结果"。您不能占用节点中的执行线程,因为它是协作式多任务处理。将计算分解为小块,使用外部进程助手,将某些内容拆分为支持C++库等。

我会稍微重写一下你的代码。假设我们需要处理 1000000 个项目,并且有一个(CPU 绑定,但有时可以调用)函数computeItem()和 io 绑定postItem()。我们希望在后台处理尽可能多的项目,但仍具有响应事件循环。为简单起见,不使用外部工作线程/队列/服务。可能的解决方案:

var desiredLatency = 10; // ms
function doBackgroundWork() {
  var start = new Date();
  var end;
  var item; 
  while (item = computeItem()) {
    postItem(item);
    if (end - start >= desiredLatency) {
      setImmediate(doBackgroundWork); // resume at next event loop invocation after processing other handlers
    }
  }
}
http.createServer(function(req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World');
}).listen(5000, '127.0.0.1');
doBackgroundWork();