2012-02-15 12 views
9

एक समय संवेदनशील परियोजना पर काम करते समय, मैंने उपलब्ध समय घटनाओं की ग्रैन्युलरिटी का परीक्षण करने के लिए नीचे दिए गए कोड का उपयोग किया, पहले फ़ायरफ़ॉक्स में मेरी डेस्कटॉप मशीन पर, फिर मेरे लिनक्स सर्वर पर node.js कोड के रूप में। फ़ायरफ़ॉक्स ने 1 एमएमएस टाइमआउट पर 200 एफपीएस औसत अनुमानित परिणामों का अनुमान लगाया और संकेत दिया कि मेरे पास 5 एमएमएस ग्रैन्युलरिटी के साथ समय की घटनाएं थीं।क्यों node.js setTimeout (func, 1.0) को संभालता है गलत तरीके से?

अब मुझे पता है कि अगर मैंने 0 का टाइमआउट मान इस्तेमाल किया है, तो क्रोम वी 8 इंजन नोड.जेएस का निर्माण वास्तव में किसी ईवेंट में टाइमआउट को प्रतिनिधि नहीं करेगा बल्कि तुरंत इसे संसाधित करेगा। जैसा कि अपेक्षित था, संख्या 60,000 एफपीएस औसत थी, स्पष्ट रूप से सीपीयू क्षमता (और शीर्ष के साथ सत्यापित) पर लगातार प्रसंस्करण। लेकिन 1 एमएम टाइमआउट के साथ संख्याएं अभी भी लगभग 3.5-4 हजार चक्र() प्रति सेकेंड थीं, जिसका अर्थ है कि नोड.जेएस संभवतः 1 एमएम टाइमआउट का सम्मान नहीं कर सकता है जो सैद्धांतिक अधिकतम 1 हजार चक्र() प्रति सेकंड बना देगा।

संख्या की श्रेणी के साथ खेलना, मैं मिलता है:

  • 2ms: ~ 100 एफपीएस (सच टाइमआउट, लिनक्स पर समय की घटनाओं की 10ms विवरण के स्तर को दर्शाता है)
  • 1.5: एक ही
  • 1,0001: एक ही
  • 1.0: 3,500 - 4,500 एफपीएस
  • 0.99: 2,800 - 3,600 एफपीएस
  • 0.5: 1,100 - 2,800 एफपीएस
  • 0.0001: 1,800 - 3,300 एफपीएस
  • 0.0: ~ 60,000 एफपीएस

setTimeout के व्यवहार (समारोह, 0) क्षम्य लगता है, क्योंकि ECMAScript विनिर्देश शायद एक वास्तविक करने के लिए कॉल सौंपने setTimout का कोई वादा करता है ओएस-स्तर बाधा। लेकिन कुछ भीx < = 1.0 के लिए परिणाम स्पष्ट रूप से हास्यास्पद है। मैंने देरी के लिए एक स्पष्ट समय दिया, और एक्स विलंब पर एन कॉल के लिए सैद्धांतिक न्यूनतम समय होना चाहिए (एन -1) * एक्स। क्या बिल्ली V8/Node.js कर रहा है?

var timer, counter = 0, time = new Date().getTime(); 

function cycle() { 
    counter++; 
    var curT = new Date().getTime(); 
    if(curT - time > 1000) { 
     console.log(counter+" fps"); 
     time += 1000; 
     counter = 0; 
    } 
    timer = setTimeout(cycle, 1); 
} 

function stop() { 
    clearTimeout(timer); 
} 

setTimeout(stop, 10000); 
cycle(); 
+0

क्या मेरा अनुमान है कि कि Node.js टीम जंगली कि 'इस्तेमाल किया 1' एक टाइमआउट मान के रूप में 'यथाशीघ्र' मतलब करने के लिए कोड मनाया है। मुझे बहुत सारे प्रोग्रामर (स्वयं शामिल) लिखने में संकोच करते हैं 'सेटटाइमआउट (कुछफनक, 0)' क्योंकि '0' किसी भी तरह' गलत लगता है '... शून्य का टाइमआउट कोई टाइमआउट नहीं है। '1' इस तरह के कोड में ASAP का मतलब अगले तार्किक मान लगता है। तो नोड.जेएस कोड में शायद 'if (timeout> 1) {scheduleTimeout (someFunc, timeout);} else {scheduleNextTick (someFunc);} ' –

+0

बहुत ही रोचक सवाल बीटीडब्लू है। मुझे इस तरह के शोध से प्यार है! –

उत्तर

1

पूर्णता के लिए मैं NodeJS कार्यान्वयन के लिए बाहर बिंदु करना चाहते हैं:

https://github.com/nodejs/node-v0.x-archive/blob/master/lib/timers.js#L214

कौन सा है:

निष्क्रिय समय समाप्ति

:

// Timeout values > TIMEOUT_MAX are set to 1. 
var TIMEOUT_MAX = 2147483647; // 2^31-1 
... 
exports.setTimeout = function(callback, after) { 
    var timer; 

    after *= 1; // coalesce to number or NaN 

    if (!(after >= 1 && after <= TIMEOUT_MAX)) { 
     after = 1; // schedule on next tick, follows browser behaviour 
    } 

    timer = new Timeout(after); 
    ... 
} 

इस बयान याद रखें

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

इस तकनीक libev पुस्तिका में वर्णित है: http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Be_smart_about_timeouts

और हम same timeout value (1) यहाँ गुजरती हैं।

Timer के लिए कार्यान्वयन यहाँ है:
https://github.com/nodejs/node-v0.x-archive/blob/master/src/timer_wrap.cc

+0

वापस देखकर, मैं अनुमान लगा सकता हूं कि 0 HonoredMule

5
node.js api docs for setTimeout(cb, ms) (जोर मेरा) से

:

यह ध्यान रखें कि अपने कॉलबैक शायद बिल्कुल मिलीसेकेंड देरी में नहीं बुलाया जाएगा महत्वपूर्ण है - Node.js कोई गारंटी के बारे में बनाता है सटीक समय जब कॉलबैक आग लगेगा, न ही ऑर्डरिंग चीजों में आग लग जाएगी। कॉलबैक को निर्दिष्ट समय के लिए जितना संभव हो सके बंद कर दिया जाएगा।

मुझे लगता है कि "जितना संभव हो सके" का मतलब आपके लिए कार्यान्वयन टीम के लिए कुछ अलग है।

[संपादित करें] संयोग से, ऐसा लगता है कि setTimeout() function (हालांकि apparently part of the HTML5 draft) किसी भी विनिर्देश द्वारा अनिवार्य नहीं है। इसके अलावा, वहां 4-10 मिमी डी-फैक्टो न्यूनतम स्तर का ग्रैन्युलरिटी प्रतीत होता है, इसलिए ऐसा लगता है कि "यह कैसा है"।

ओपन सोर्स सॉफ़्टवेयर के बारे में बड़ी बात यह है कि आप अपनी आवश्यकताओं के अनुसार उच्च रिज़ॉल्यूशन को शामिल करने के लिए पैच का योगदान कर सकते हैं!

+0

@ होनोरमूल: आपकी उम्मीदों के कारण या उन सॉफ्टवेयर के कार्यान्वयन के बारे में विनिर्देशों के कारण उन आंकड़ों को "कोई समझ नहीं आता"? – maerics

+0

संयोग से, setInterval केवल तब चलता है जब अंतराल> = 1.0 node.js में होता है, और हमेशा हर जगह एक वास्तविक बाधा का उपयोग करता है, जो कि लिनक्स पर 5 एमएमएस ग्रैन्युलरिटी और फ़ायरफ़ॉक्स में 4 एमएमएस ग्रैन्युलरिटी दिखाता है। जब हम ओएस-स्तरीय इंटरप्ट ग्रैन्युलरिटी की दया पर हैं तो "कोई गारंटी नहीं" चीज की उम्मीद है, लेकिन इससे प्रति सेकंड 4,000 इंटरप्ट उत्पन्न नहीं होंगे। मैं जो खोज रहा हूं वह एक एपीआई स्तर (यानी 0 => तत्काल कॉल, <= 1.0 => से सीधे नोड की घटना कतार,> 1.0 => सही बाधा) से/what/Node.js कर रहा है, इसका एक स्पष्टीकरण है। दस्तावेज कुछ भी नहीं कहता है। – HonoredMule

+0

क्षमा करें, पहली टिप्पणी पोस्ट करने के लिए कभी नहीं था (पैराग्राफ ब्रेक चाहता था) - मैंने संपादन समय से बाहर होने के बाद इसे हटा दिया। वैसे भी, मेरी अपेक्षाओं को अधिक विस्तृत दस्तावेज़ीकरण के बिना सेट करना मुश्किल है ... इसलिए सवाल। – HonoredMule

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