如何在node.js中实现setTimeout [英] How is setTimeout implemented in node.js

查看:222
本文介绍了如何在node.js中实现setTimeout的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否有人知道如何在node.js中实现 setTimeout .我相信我在某处读到它不是V8的一部分.我很快尝试找到实现,但在源(BIG)中找不到它.例如,我发现了这个 timer_wrap.cc .但是这些文件并不能完全回答我所有的问题.

I was wondering if anybody knows how setTimeout is implemented in node.js. I believe I have read somewhere that this is not part of V8. I quickly tried to find the implementation, but could not find it in the source(BIG).I for example found this timers.js file, which then for example links to timer_wrap.cc. But these file do not completely answer all of my questions.

  • V8是否具有setTimeout实现?我也从源头猜测答案是否定的.
  • setTimeout如何实现? javascript还是本机还是两者结合?在timers.js中,我假设两者都符合:

  • Does V8 have setTimeout implementation? I guess also from the source the answer is no.
  • How is setTimeout implemented? javascript or native or combination of both? From timers.js I assume something along the line of both:

var Timer = process.binding('timer_wrap').Timer;`

  • 添加多个计时器(setTimeout)时,node.js如何知道首先执行哪个?是否将所有计时器添加到集合中(排序)?如果已排序,则找到需要执行的超时时间是否为O(1)和O(log n)以便插入?但是再在timers.js中,我看到它们使用链表了吗?

  • When adding multiple timers(setTimeout) how does node.js know which to execute first? Does it add all the timers to a collection(sorted)? If it is sorted then finding the timeout which needs to be executed is O(1) and O(log n) for insertion? But then again in timers.js I see them use a 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使用率,但不是很多?

    you get a little bit of CPU usage but not that much?

    推荐答案

    您已经完成了大部分工作. V8不提供setTimeout的实现,因为它不是ECMAScript的一部分.您使用的函数是在timers.js中实现的,该计时器创建了Timeout对象的实例,该对象是C类的包装器.

    You've done most of the work already. V8 doesn't provides an implementation for setTimeout because it's not part of ECMAScript. The function you use is implemented in timers.js, which creates an instance of a Timeout object which is a wrapper around a C class.

    来源中有一条注释,描述了他们如何管理计时器.

    There is a comment in the source describing how they are managing the timers.

    // 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.

    Which indicates it's using a double linked list which is #4 in the linked article.

    如果没有一个请求,但是有成千上万个请求,则全部 使用某种具有相同超时值的超时,然后 可以做得更好:

    If there is not one request, but many thousands (millions...), all employing some kind of timeout with the same timeout value, then one can do even better:

    开始超时时,请计算超时值,然后将 超时在列表的末尾.

    When starting the timeout, calculate the timeout value and put the timeout at the end of the list.

    然后使用ev_timer在超时时间开始时触发 列表可能会触发(例如,使用技术3).

    Then use an ev_timer to fire when the timeout at the beginning of the list is expected to fire (for example, using the technique #3).

    有活动时,从列表中删除计时器, 重新计算超时,再次将其追加到列表的末尾,然后 如果从ev_timer的开头获取,请确保对其进行更新 列表.

    When there is some activity, remove the timer from the list, recalculate the timeout, append it to the end of the list again, and make sure to update the ev_timer if it was taken from the beginning of the list.

    这样,一个人可以在O(1)时间里管理无限数量的超时 用于启动,停止和更新计时器,但要付出一定的代价 严重的并发症,并且必须使用恒定的超时时间.常数 超时可确保列表保持排序.

    This way, one can manage an unlimited number of timeouts in O(1) time for starting, stopping and updating the timers, at the expense of a major complication, and having to use a constant timeout. The constant timeout ensures that the list stays sorted.

    Node.js是围绕异步操作设计的,而setTimeout是其中的重要部分.我不会尝试变得棘手,只需使用它们提供的功能即可.相信它足够快,直到您在特定情况下证明它是瓶颈为止.不要卡在过早的优化上.

    Node.js is designed around async operations and setTimeout is an important part of that. I wouldn't try to get tricky, just use what they provide. Trust that it's fast enough until you've proven that in your specific case it's a bottleneck. Don't get stuck on premature optimization.

    更新

    发生的事情是,您实际上在顶层有一个超时字典,因此所有100ms超时都组合在一起.每当添加新的超时或最早的超时触发器时,它就会被添加到列表中.这意味着最早的超时(将触发最快的超时)在列表的开头.该列表只有一个计时器,它是根据直到列表中第一个项目到期的时间设置的.

    What happens is you've got essentially a dictionary of timeouts at the top level, so all 100ms timeouts are grouped together. Whenever a new timeout is added, or the oldest timeout triggers, it is appended to the list. This means that the oldest timeout, the one which will trigger the soonest, is at the beginning of the list. There is a single timer for this list, and it's set based on the time until the first item in the list is set to expire.

    如果以相同的超时值分别调用setTimeout 1000次,它们将按照调用setTimeout的顺序添加到列表中,并且无需排序.这是一个非常有效的设置.

    If you call setTimeout 1000 times each with the same timeout value, they will be appended to the list in the order you called setTimeout and no sorting is necessary. It's a very efficient setup.

    这篇关于如何在node.js中实现setTimeout的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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