libuv 和 Node.js 实际上是如何调度计时器的? [英] How does libuv and Node.js actually schedule timers?

查看:37
本文介绍了libuv 和 Node.js 实际上是如何调度计时器的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Node.js 中,libuv 和操作系统实际上是如何调度像 setTimeout 和 setInterval 这样的定时器的?我看到节点进程没有使用 CPU,直到计时器触发.这是否意味着操作系统会调度计时器,并在计时器被触发时唤醒 Node 进程?如果是这样,操作系统如何调度计时器以及硬件究竟如何执行它?

How does libuv and the operating system actually schedule timers like setTimeout and setInterval in Node.js? I see that no CPU is used by the node process until a timer fires. Does this mean the OS schedules the timer, and wakes up the Node process when the timer is fired? If so, how does an OS schedule a timer and how exactly does the hardware execute it?

推荐答案

定时器回调作为 NodeJS 事件循环的一部分执行.当您调用 setTimeoutsetInterval 时,libuv(实现 NodeJS 事件循环的 C 库)在称为计时器堆的最小堆"数据结构中创建一个计时器.在这个数据结构中,它跟踪每个计时器到期的时间戳.

Timer callbacks are executed as part of the NodeJS event loop. When you call setTimeout or setInterval, libuv (the C library which implements the NodeJS event loop) creates a timer in a 'min heap' data structure which is called the timers heap. In this data structure, it keeps track of the timestamp that each timer expires at.

在事件循环的每次新迭代开始时,libuv 调用 uv__update_time,后者又调用系统调用来获取当前时间并将当前循环时间更新到毫秒精度.(https://github.com/nodejs/node/blob/master/deps/uv/src/unix/core.c#L375)

At the start of each fresh iteration of the event loop, libuv calls uv__update_time which in turn calls a syscall to get the current time and updates the current loop time up to a millisecond precision. (https://github.com/nodejs/node/blob/master/deps/uv/src/unix/core.c#L375)

紧接在该步骤之后是事件循环迭代的第一个主要阶段,即计时器阶段.在这个阶段,libuv 调用 uv__run_timers 来处理所有过期定时器的回调.在这个阶段,libuv 遍历定时器堆,根据它刚刚使用 uv__update_time 更新的循环时间"来识别过期的定时器.然后它调用所有那些过期定时器的回调.

Right after that step comes the first major phase of the event loop iteration, which is timers phase. At this phase, libuv calls uv__run_timers to process all the callbacks of expired timers. During this phase, libuv traverses the timers heap to identify expired timers based on the 'loop time' it just updated using uv__update_time. Then it invokes the callbacks of all those expired timers.

以下是 NodeJS 中事件循环实现的编辑片段,以突出我刚刚描述的内容.

Following is a redacted snippet from the event loop implementation in NodeJS to highlight what I just described.

while (r != 0 && loop->stop_flag == 0) {
    uv__update_time(loop);
    uv__run_timers(loop);
    
    // ...redacted for brevity...

    r = uv__loop_alive(loop);
    if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT)
      break;
  }

我前段时间写了一系列关于 NodeJS 事件循环的文章.我希望该系列中的这篇文章会有所帮助.https://blog.insiderattack.net/timers-immediates-and-process-nexttick-nodejs-event-loop-part-2-2c53fd511bb3

I wrote a series of articles on NodeJS event loop some time back. I hope this article from that series would be helpful. https://blog.insiderattack.net/timers-immediates-and-process-nexttick-nodejs-event-loop-part-2-2c53fd511bb3

这篇关于libuv 和 Node.js 实际上是如何调度计时器的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆