Mam pętlę, która musi być uruchamiana 200 milionów razy w przeglądarce. Jest to symulator, którego kilka osób musi regularnie używać. Uruchomienie trwa około 15 minut, ale w tym czasie przeglądarki często wyświetlają ostrzeżenie z "zbyt długim skryptem" itd. I całkowicie zawieszają Firefoksa podczas działania. Oznacza to również, że strona nie aktualizuje mojego wskaźnika statusu (który jest tylko liczbą).Zapobieganie blokowaniu przeglądarki JavaScript w dużej pętli
Mam googled "wydajność javascript" i przeczytać pierwsze 4 strony trafień. Niektórzy omawiają nowe słowo kluczowe "yield", ale jest tylko jeden opis i przykład, które uważam za niezrozumiałe, np. "Funkcja zawierająca słowo kluczowe yield jest generatorem, a kiedy go nazwiesz, to parametry formalne są powiązane z rzeczywistymi argumentami, ale ciało nie jest faktycznie oceniane". Czy yield
ustępuje UI?
Jednym z niewielu rozwiązań znalazłem jest to stary post, który korzysta z przestarzałej wywoływanego argumentu, a licznik nazywać się: http://www.julienlecomte.net/blog/2007/10/28/
Jednak powyższy przykład nie zawiera żadnych zmiennych pętli lub stan, a kiedy je dodaję, rozpada się, a mój wynik netto zawsze wynosi zero.
To również nie zrobić wyrwy, ale znalazłem kilka innych przykładów, które za pomocą kawałek „Indeks% 100 == 0” przy każdej iteracji. Jednak wydaje się, że jest to powolny sposób. Na przykład. to:
How to stop intense Javascript loop from freezing the browser
Ale to nie ma żadnego sposobu, aby zaktualizować postęp, a nie poddawać się w interfejsie (tak nadal wisi przeglądarkę). Tutaj jest to wersja testowa, która zawiesza przeglądarkę podczas wykonania:
<!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>
i tu jest kolejna próba którym stats.a
jest zawsze zero (tak przypuszczam istnieje jakiś problem określania zakresu):
<!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>
I Spędziłem 48 godzin próbując to zadziałać - albo jestem bardzo głupi, albo to jest bardzo trudne. Jakieś pomysły?
Kilka osób zasugerowało pracowników internetowych. Próbowałem kilka dni, aby uzyskać jego pracy, ale nie mogłem znaleźć podobny przykład, który przechodzi szereg itd. Poniższy kod była moja ostatnia próba dostać pracę, ale wynik jest zawsze 0, gdy powinna być 100000 Tj zawiedzie w taki sam sposób, jak mój drugi przykład powyżej zawodzi.
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);
}
wyjście wypadkową: 0
od JS jest gwintowany zwykle pojedyncze, nie sądzę, istnieje jakikolwiek sposób wokół niego. Jeśli jednak korzystasz tylko z nowszych przeglądarek, możesz zajrzeć do pracowników internetowych, którzy mogą utworzyć nowy wątek do pracy: https://developer.mozilla.org/en-US/docs/DOM/Using_web_workers – kennypu
@kennypu Powinieneś opublikować to jako odpowiedź. –
Twoim problemem z wydajnością może być również stała manipulacja DOM (co 5 ms), która jest BARDZO kosztowna. Spróbuj zaktualizować DOM w różnym tempie, powiedz co 10-20 sekund i zobacz, czy to sprawi, że będzie działał lepiej/szybciej. – elclanrs