我想知道是否有人知道如何的setTimeout在node.js中实现 我相信我已经读的地方,这不是V8的一部分。 我很快就试图找到执行,但在源无法找到它(BIG)。我如发现此timers.js文件,然后例如链接到timer_wrap.cc 。 但是,这些文件没有完全回答我所有的问题。
- 难道V8已经
setTimeout
实施? 我也想从源头答案是否定的。 如何setTimeout
实施? JavaScript或天然或两者的组合? 从timers.js我想沿着这两个线的东西:
var Timer = process.binding('timer_wrap').Timer;`
当添加多个定时器(setTimeout的)如何的node.js知道哪个先执行? 是否所有的计时器添加到集合(排序)? 如果是排序,然后找到需要被执行的超时时间为O(1)和O(log n)的用于插入? 但随后又在timers.js我看到他们用一个LinkedList?
- 但话又说回来加入了很多定时器是不是在所有的问题吗?
当执行这个脚本:
var x = new Array(1000), len = x.length; /** * Returns a random integer between min and max * Using Math.round() will give you a non-uniform distribution! */ function getRandomInt (min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } var y = 0; for (var i = 0; i < len; i++) { var randomTimeout = getRandomInt(1000, 10000); console.log(i + ', ' + randomTimeout + ', ' + ++y); setTimeout(function () { console.log(arguments); }, randomTimeout, randomTimeout, y); }
你得到的CPU使用率的一点点,但没有那么多吗?
- 我想知道如果我实现所有这些回调逐一排序列表,如果我会得到更好的性能?
你做的大部分工作已经。 V8并没有提供一个实现setTimeout
,因为它不是ECMAScript的一部分。 您使用的功能在timers.js实现,这将创建一个实例Timeout
对象,它是围绕一个C类的包装。
有源描述他们是如何管理计时器评论。
// Because often many sockets will have the same idle timeout we will not
// use one timeout watcher per item. It is too much overhead. Instead
// we'll use a single watcher for all sockets with the same timeout value
// and a linked list. This technique is described in the libev manual:
// http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Be_smart_about_timeouts
这表明它使用双链表是链接的文章#4。
如果没有一个请求,但成千上万(百万...),所有使用某种具有相同的超时值超时,那么可以做得更好:
当启动超时,计算超时值,并把超时在列表的末尾。
然后使用ev_timer火当在列表的开头超时,预计火(例如,使用该技术#3)。
当有一些活动,从列表中删除的计时器,重新计算超时,再次追加到列表的末尾,并确保更新ev_timer如果它是从列表的开始拍摄。
这样一来,一个可以在O管理超时的数量不受限制(1)时间启动,停止和更新计时器,在主要并发症的费用,并且必须使用恒定超时。 恒超时确保清单是排序。
Node.js的是围绕着异步操作和setTimeout
是这方面的一个重要组成部分。 我不会试图变得棘手,只需使用他们提供什么样的。 信托,它的速度不够快,直到你已经证明,在特定情况下,它是一个瓶颈。 不要沉浸于过早的优化。
UPDATE
会发生什么事是你已经有了本质上是在顶层超时的字典,所以所有的100毫秒超时组合在一起。 每当一个新的超时被添加,或者最古老的超时触发,会被添加到列表中。 这意味着,最早的超时,一个将触发最快,在列表的开头。 没有此列表中的一个计时器,它的基础上,直到在列表中的第一项设置为过期时间设置。
如果调用setTimeout
每1000次相同的超时值,它们将被添加到你调用顺序列表setTimeout
和不需要进行排序。 这是一个非常有效的设置。
没问题,有许多计时器! 当紫外线循环电话民意调查,它传递超时参数把它与所有定时器的最接近定时器。
[接近的所有定时器的定时器]
https://github.com/joyent/node/blob/master/deps/uv/src/unix/timer.c #120
RB_MIN(uv__timers, &loop->timer_handles)
[传递超时参数轮询API]
https://github.com/joyent/node/blob/master/deps/uv/src/unix/core.c #276
timeout = 0;
if ((mode & UV_RUN_NOWAIT) == 0)
timeout = uv_backend_timeout(loop);
uv__io_poll(loop, timeout);
注:在Windows操作系统上,它几乎是同样的逻辑