2012-11-28 17 views
20

में कैसे कार्यान्वित किया गया है, मैं सोच रहा था कि कोई भी जानता है कि कैसे setTimeout node.js. में लागू किया गया है। मेरा मानना ​​है कि मैंने कहीं पढ़ा है कि यह वी 8 का हिस्सा नहीं है। मैंने जल्दी ही कार्यान्वयन को खोजने की कोशिश की, लेकिन इसे स्रोत (बीआईजी) में नहीं मिला। उदाहरण के लिए यह timers.js फ़ाइल मिली, जो कि उदाहरण के लिए timer_wrap.cc से लिंक है। लेकिन ये फाइल पूरी तरह से मेरे सभी सवालों का जवाब नहीं देती हैं।setTimeout को node.js

  • क्या वी 8 में setTimeout कार्यान्वयन है? मुझे लगता है कि स्रोत से भी जवाब नहीं है।
  • setTimeout कैसे लागू किया गया है? जावास्क्रिप्ट या देशी या दोनों का संयोजन?

    var Timer = process.binding('timer_wrap').Timer;` 
    
  • जोड़ते एकाधिक टाइमर (setTimeout) कैसे पता Node.js पहले निष्पादित करने के लिए जो कार्य करता है: timers.js से मैं दोनों की रेखा के साथ कुछ मान? क्या यह सभी टाइमर को संग्रह (क्रमबद्ध) में जोड़ता है? यदि इसे सॉर्ट किया गया है तो निष्पादन के लिए ओ (1) और ओ (लॉग एन) निष्पादित करने की आवश्यकता वाले टाइमआउट को ढूंढना है? लेकिन फिर timers.js में फिर से मैं उन्हें एक लिंक्डलिस्ट का उपयोग देखता हूँ?

  • लेकिन फिर फिर से बहुत सारे टाइमर जोड़ना कोई समस्या नहीं है?

    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 उपयोग का एक छोटा सा मिलता है, लेकिन वह ज्यादा नहीं:

  • जब इस स्क्रिप्ट पर कार्य करते?

  • मुझे आश्चर्य है कि अगर मैं बेहतर प्रदर्शन प्राप्त करूँगा तो मैं इन सभी कॉलबैक को एक क्रमबद्ध सूची में एक-एक करके लागू कर सकता हूं?

उत्तर

17

आपने पहले से ही अधिकांश काम किया है। वी 8 setTimeout के लिए कार्यान्वयन प्रदान नहीं करता है क्योंकि यह ईसीएमएस्क्रिप्ट का हिस्सा नहीं है। आपके द्वारा उपयोग किया जाने वाला फ़ंक्शन timers.js में कार्यान्वित किया गया है, जो Timeout ऑब्जेक्ट का उदाहरण बनाता है जो एक सी क्लास के चारों ओर एक रैपर है।

स्रोत में एक टिप्पणी है कि वे टाइमर का प्रबंधन कैसे कर रहे हैं।

// 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 है उपयोग कर रहा है।

अगर वहाँ एक अनुरोध नहीं है, लेकिन कई हजारों (लाखों लोगों की ...), सभी ही टाइमआउट मान के साथ समय समाप्ति के कुछ प्रकार के रोजगार, फिर एक और भी बेहतर कर सकते हैं:

जब शुरू करने टाइमआउट, टाइमआउट मान की गणना करें और सूची के अंत में टाइमआउट डालें।

फिर सूची की शुरुआत में टाइमआउट को आग लगने की उम्मीद है (उदाहरण के लिए, तकनीक # 3 का उपयोग करके) को आग लगने के लिए ev_timer का उपयोग करें।

जब कुछ गतिविधि है, सूची से टाइमर को हटाने, , टाइमआउट पुनर्गणना यह सूची के अंत में फिर से जोड़ने और ev_timer अद्यतन करने के लिए यकीन है कि अगर यह की शुरुआत से लिया गया था बनाने के सूची।

इस तरह, एक, शुरू करने को रोकने और टाइमर को अद्यतन करने, एक प्रमुख जटिलता की कीमत पर, और एक निरंतर टाइमआउट उपयोग करने के लिए होने के लिए एक असीमित (1) समय हे में समय समाप्ति की संख्या का प्रबंधन कर सकते हैं। निरंतर टाइमआउट सुनिश्चित करता है कि सूची क्रमबद्ध रहती है।

नोड.जेएस एसिंक ऑपरेशंस के आसपास डिज़ाइन किया गया है और setTimeout इसका एक महत्वपूर्ण हिस्सा है। मैं मुश्किल पाने की कोशिश नहीं करता, बस जो कुछ भी प्रदान करता हूं उसका उपयोग करें। विश्वास करें कि यह तब तक पर्याप्त तेज़ है जब तक आप साबित न करें कि आपके विशिष्ट मामले में यह एक बाधा है। समयपूर्व अनुकूलन पर अटक मत जाओ।

अद्यतन

क्या होता है आप शीर्ष स्तर पर समय समाप्ति की अनिवार्य रूप से एक शब्दकोश है, इसलिए सभी 100ms समय समाप्ति साथ रखे जाते हैं मिल गया है है। जब भी कोई नया टाइमआउट जोड़ा जाता है, या सबसे पुराना टाइमआउट ट्रिगर्स होता है, तो यह सूची में शामिल होता है। इसका मतलब है कि सबसे पुराना टाइमआउट, जो जल्द से जल्द ट्रिगर करेगा, सूची की शुरुआत में है। इस सूची के लिए एक टाइमर है, और यह उस समय के आधार पर सेट है जब तक कि सूची में पहली आइटम समाप्त होने के लिए सेट नहीं हो जाती है।

यदि आप setTimeout प्रत्येक बार एक ही टाइमआउट मान के साथ 1000 बार कॉल करते हैं, तो उन्हें setTimeout नामक क्रम में सूची में जोड़ा जाएगा और कोई सॉर्टिंग आवश्यक नहीं है। यह एक बहुत ही कुशल सेटअप है।

+0

इस उदाहरण में टाइमआउट हमेशा समान होते हैं? 60 सेकंड? – Alfred

+0

तो आप 60 सेकंड में कई चीजें होने की इच्छा रखते हैं, और आप यह पता लगाने की कोशिश कर रहे हैं कि उन सभी चीजों को एक साथ जोड़ना है या प्रत्येक के लिए अलग-अलग सेटटाइम बनाना है? –

+0

कोई खेद नहीं है। आपके द्वारा लिंक किया गया दस्तावेज़ 60 सेकंड देरी है। मेरी देरी कुछ भी हो सकती है और बहुत कुछ! – Alfred

3

कई टाइमर के साथ कोई समस्या नहीं! जब यूवी लूप कॉल मतदान करते हैं, तो यह सभी टाइमर के निकटतम टाइमर के साथ टाइमआउट तर्क देता है।

[सभी टाइमर के निकटतम टाइमर]
https://github.com/joyent/node/blob/master/deps/uv/src/unix/timer.c # 120

RB_MIN(uv__timers, &loop->timer_handles) 


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); 

नोट [मतदान पर एपीआई टाइमआउट तर्क पारित]: पर विंडोज ओएस, यह लगभग एक ही तर्क है

संबंधित मुद्दे