2012-12-28 19 views
7

मेरे पास एक लूप है जिसे ब्राउज़र में 200 मिलियन बार चलाने की आवश्यकता है। यह एक सिम्युलेटर है जिसे कई लोगों को नियमित रूप से उपयोग करने की आवश्यकता होती है। इसे चलाने में लगभग 15 मिनट लगते हैं, लेकिन इस समय के दौरान, ब्राउज़र अक्सर "इस स्क्रिप्ट में बहुत लंबा समय ले रहा है" के साथ एक चेतावनी पॉप अप करेगा, और यह फ़ंक्शन के दौरान फ़ायरफ़ॉक्स को पूरी तरह से लटकता है। इसका यह भी अर्थ है कि पृष्ठ मेरा स्टेटस इंडिकेटर अपडेट नहीं करता है (जो कि केवल एक संख्या है)।बड़े लूप पर ब्राउजर को लॉक करने से जावास्क्रिप्ट को रोकें

मैंने "जावास्क्रिप्ट उपज" गुगल किया है और हिट के पहले 4 पृष्ठ पढ़े हैं। कुछ नए "उपज" कीवर्ड पर चर्चा करते हैं, लेकिन केवल एक विवरण और उदाहरण है, जिसे मुझे समझ में नहीं आता है, उदा। "उपज कीवर्ड युक्त फ़ंक्शन एक जनरेटर होता है। जब आप इसे कॉल करते हैं, तो औपचारिक पैरामीटर वास्तविक तर्कों से बंधे होते हैं, लेकिन इसका शरीर वास्तव में मूल्यांकन नहीं किया जाता है"। यूआई को yield उपज है? , http://www.julienlecomte.net/blog/2007/10/28/

हालांकि, ऊपर के उदाहरण किसी भी पाश चर या राज्य शामिल नहीं है:

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

यह भी चंकिंग नहीं करता है, लेकिन मुझे कुछ अन्य उदाहरण मिल गए हैं जो प्रत्येक पुनरावृत्ति पर "अनुक्रमणिका% 100 == 0" का उपयोग करके खंडित हैं। हालांकि, ऐसा करने का यह धीमा तरीका प्रतीत होता है। जैसे इस:

How to stop intense Javascript loop from freezing the browser

लेकिन यह प्रगति को अद्यतन करने के लिए किसी भी तरह नहीं है, और यूआई के लिए उपज नहीं है (ताकि अभी भी ब्राउज़र लटका हुआ है)।

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<script> 
var spins = 1000000 
var chunkSize = 1000; 
var chunk; 
function Stats() {this.a=0}; 
var stats = new Stats();    
var big; 

var index = 0; 

var process = function() { 
    for (; index < spins; index++) { 
    stats.a++; 
    big = (big/3.6)+ big * 1.3 * big/2.1; 
    console.write(big); 
    // Perform xml processing 
    if (index + 1 < spins && index % 100 == 0) { 
     document.getElementById("result").innerHTML = stats.a; 
     setTimeout(process, 5); 
    } 
    } 
    document.getElementById("result").innerHTML = stats.a; 
}; 


</script> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>Untitled Document</title> 
</head> 

<body onload="process()"> 
<div id=result>result goes here.</div> 
</body> 
</html> 

और यहाँ एक और प्रयास है जो stats.a हमेशा शून्य है (तो मुझे लगता है कुछ scoping मुद्दा नहीं है):: यहाँ एक परीक्षण संस्करण है जो निष्पादन के दौरान ब्राउज़र लटका हुआ है

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<script> 
var spins = 1000000 
var chunkSize = 1000; 
var chunk; 
function Stats() {this.a=0}; 
var stats = new Stats();    

function doIt() { 
    function spin() { 
     for (spinIx=0; (spinIx<chunkSize) && (spinIx+chunk < spins); spinIx++) { 
      stats.a++; 
     } 
    }   

    for (chunk =0; chunk < spins; chunk+=chunkSize){ 
     setTimeout(spin, 5); 
      document.getElementById("result").innerHTML = stats.a; 
     } 
     document.getElementById("result").innerHTML = stats.a; 
} 

</script> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>Untitled Document</title> 
</head> 

<body onload="doIt()"> 
<div id=result>result goes here.</div> 
</body> 
</html> 

मैं इस काम को पाने के लिए 48 घंटे बिताए हैं - या तो मैं बहुत मूर्ख हूं या यह बहुत कठिन है। कोई विचार?

कई लोगों ने वेब श्रमिकों का सुझाव दिया है। मैंने अपना काम करने के लिए कई दिनों की कोशिश की, लेकिन मुझे एक ऐसा उदाहरण नहीं मिला जो एक संख्या उत्तीर्ण करता है। नीचे दिया गया कोड यह काम करने का मेरा आखिरी प्रयास था, लेकिन परिणाम हमेशा 0 होता है जब यह 100000 होना चाहिए। यह उसी तरह विफल रहता है जिस पर मेरा दूसरा उदाहरण विफल रहता है।

spinMaster.html:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
</head> 
<body> 
<script> 
if(typeof(Worker)==="undefined") { 
    document.write("<h1>sorry, your browser doesnt support web workers, please use firefox, opera, chorme or safari</h1>"); 
    } 
var worker =new Worker("spinWorker.js"); 

worker.postMessage({times:1000000}); 

worker.onmessage=function(event){ 
document.getElementById("result").innerHTML=event.data; 
}; 
</script> 

<div id="result">result goes here</div> 
</body> 
</html> 

spinWorker.js

function State() { 
    this.a=0; 
} 

var state = new State(); 

self.addEventListener('message', spin, false); 

function spin(e) { 
    var times, i; 

    times = e.data.times; 
//times = 1000000; // this doesnt work either. 

    for(i;i<times;i++) { 
     state.a++; 
    } 

    self.postMessage(state.a); 
} 

परिणामी उत्पादन: 0

+4

के बाद से जे एस है एक लड़ी आमतौर पर, मुझे नहीं लगता कि यह चारों ओर किसी भी तरह से है। यदि आप केवल नए ब्राउज़र का समर्थन कर रहे हैं, तो हो सकता है कि आप वेब श्रमिकों को देखना चाहें, जो काम करने के लिए एक नया धागा पैदा कर सकते हैं: https://developer.mozilla.org/en-US/docs/DOM/Using_web_workers – kennypu

+0

@kennypu आपको इसे एक उत्तर के रूप में पोस्ट करना चाहिए। –

+1

आपकी प्रदर्शन समस्या लगातार डीओएम हेरफेर (हर 5 एमएमएस) हो सकती है, जो बहुत महंगा है। डीओएम को एक अलग दर पर अपडेट करने का प्रयास करें, हर 10-20 सेकंड कहें और देखें कि क्या यह बेहतर/तेज़ प्रदर्शन करता है। – elclanrs

उत्तर

1

के बाद से जे एस एकल थ्रेड आमतौर पर, मुझे नहीं लगता कि वहाँ के आसपास किसी भी तरह से है यह। यदि आप केवल नए ब्राउज़र का समर्थन कर रहे हैं, तो हो सकता है कि आप वेब श्रमिकों को देखना चाहें, जो काम करने के लिए एक नया धागा पैदा कर सकते हैं: http://developer.mozilla.org/en-US/docs/DOM/Using_web_workers

एकमात्र नकारात्मक पक्ष जो मैं सोच सकता हूं वह यह है कि मैंने पढ़ा है कि यह मुश्किल है वेब वर्कर्स डीबग करें क्योंकि देव टूल्स (क्रोम देव टूल्स जब तक देव चैनल, फायरबग नहीं चलाते), इसके लिए प्रोफाइलिंग का समर्थन नहीं करते हैं।

यहाँ एक अच्छा ट्यूटोरियल पाने के लिए आप शुरू कर दिया है: http://net.tutsplus.com/tutorials/javascript-ajax/getting-started-with-web-workers/

4

वेब श्रमिकों बेहतर समाधान की तरह ध्वनि।

मैंने इसे जल्दी लिखा है इसलिए मुझे पता चल जाएगा कि यह काम करेगा। प्रदर्शन बहुत खराब होगा ...

संपादित करें: पोस्टर के रूप में उसी प्रारूप में बदल गया। परीक्षण

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<script> 
    var spins = 1000000 
    var chunkSize = 1000; 
    var chunk; 
    function Stats() {this.a=0}; 
    var stats = new Stats();   
    var big = 0.0; 

    var index = 0; 

    function workLoop() { 

     index += 1; 

     stats.a++; 
     big = (big/3.6)+ big * 1.3 * big/2.1; 
     console.log(big); 
     // Perform xml processing 
     document.getElementById('result').innerHTML = stats.a; 
     if (index < spins) { 
      setTimeout(workLoop, 5); 
     } 

    } 



</script> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>Untitled Document</title> 
</head> 

<body onload="workLoop()"> 
<div id="result">result goes here.</div> 
</body> 
</html> 
+0

हाय रिसीके, क्या आप समझा सकते हैं कि "अगर (इंडेक्स) भाग क्या है? मेरी समझ आप कह रहे हैं" अगर (इंडेक्स == 0) इंडेक्स = 1; "जो" इंडेक्स + = 1; " –

+0

कहने जैसा ही है हाँ, आप सही हैं। एक संपादन बनाया गया। – rissicay

-1

यह आप क्या चाहते हैं करना चाहिए:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<script> 
var spins = 1000000 
var chunkSize = 1000; 
var stats = {a:0,spins:0};    

function doIt() { 
    for (var chunk = 0; chunk < chunkSize; chunk++) { 
     stats.a++; 
    } 
    document.getElementById("result").innerHTML = stats.a; 
    if(++stats.spins < spins) setTimeout(doIt,5); 

} 

</script> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>Untitled Document</title> 
</head> 

<body onload="doIt()"> 
<div id=result>result goes here.</div> 
</body> 
</html> 
1

आपके पास अपने 1 की परीक्षा में एक काम उदाहरण के करीब है, लेकिन मैं एक तर्क त्रुटि क्यों दिखाई देता है। आपके अगर() में, आपको फ़ंक्शन से वापस लौटना होगा अन्यथा यह हमेशा उस थ्रेड के लिए प्रतिस्पर्धा करने वाले कई फ़ंक्शन चलाएगा।

var process = function() { 
    for (; index < spins; index++) { 
    stats.a++; 
    big = (big/3.6)+ big * 1.3 * big/2.1; 
    console.write(big); 
    // Perform xml processing 
    if (index + 1 < spins && index % 100 == 0) { 

document.getElementById("result").innerHTML = stats.a; 
     setTimeout(process, 5); 
     //!!!!! 
     return;//without this it'll keep iterating through the for loop without waiting for the next 5ms 
     //!!!!! 
    } 
    } 

document.getElementById("result").innerHTML = stats.a; 
}; 

नमूनों की न तो के रूप में है (अगले setTimeout के लिए प्रतीक्षा अपने 2 उदाहरण आप अपने पाश के लिए पाश के लिए पूर्ण हो जाने तक के माध्यम से पुनरावृत्ति जारी रखने में है, लेकिन प्रत्येक ब्लॉक आकार में आप बाद में एक के लिए एक समाप्ति सेट पुनरावृत्ति। यह सब 5 एमएस के लिए पूरे अनुक्रम में देरी कर रहा है, वे अभी भी सभी ढेर और 5 एमएस निष्पादित करते हैं जब आपका लूप पुनरावृत्ति शुरू होता है)

सब कुछ आप सही रास्ते पर दिखते हैं, बस छोटे हैं दोनों उदाहरणों में तर्क त्रुटियां।

+0

धन्यवाद, यह सहायक था, हालांकि मुझे वास्तव में समझ में नहीं आता कि क्या हो रहा है। मैंने यह रिटर्न जोड़ा, फिर यह 100,200 के बजाय प्रत्येक नंबर (उदाहरण के लिए 1,2,3) आउटपुट आदि। यदि मैंने वापसी के पहले && (अनुक्रमणिका> 0) जोड़ा, और वापसी से पहले एक अतिरिक्त अनुक्रमणिका ++ जोड़ा, और अब यह काम करता प्रतीत होता है। अजीब बात यह है कि मैंने इस उदाहरण की प्रतिलिपि बनाई है कि कुछ प्रकाशित उदाहरणों में से एक को कैसे करना है यह मुझे लगता है कि उन्होंने गैर वर्किंग कोड प्रकाशित किया है। –

+0

या, अच्छा बिंदु, क्योंकि आप 100 के गुणकों से शुरू कर रहे हैं, पहले पुनरावृत्ति के लिए इंडेक्स> 0 की आवश्यकता है (0% 100 == 0)। उदाहरण हैं जो प्रतिलिपि/पेस्ट तैयार हैं और जो पॉइंटर्स हैं, शायद आपके द्वारा उपयोग किए जाने वाले व्यक्ति को पॉइंटर होने की दिशा में लक्षित किया गया था। लेकिन यह रिकर्सिव फ़ंक्शंस जैसी चीजों के लिए एक आम गलती है और जैसा कि यह जावास्क्रिप्ट में था, लूप के लिए स्थगित जो "इंडेक्स" जैसे वैश्विक चर पर भरोसा करते हैं। ओह अच्छा। तो क्या आप हैं जहां आपको अभी होना चाहिए? क्या आपका एप काम कर रहा है जैसा आपने आशा की थी? – chwagssd

0

ब्राउज़र/धागे को लॉक किए बिना और वेब-श्रमिकों के उपयोग किए बिना इस प्रकार के बड़े लूपिंग के लिए उपलब्ध गिटूब पर एक लाइब्रेरी है।

कुछ हद तक प्रयोगात्मक, और बड़े रिकर्सिव लूप का समर्थन करता है, लेकिन यह आपके लिए काम कर सकता है। वादे को हल करने के लिए q.js पर निर्भर करता है।

https://github.com/sterpe/stackless.js

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

  • कोई संबंधित समस्या नहीं^_^