2014-02-12 4 views
5

Internet Explorer 8 (die ich unterstützen muss, leider nicht verhandelbar) zeigt the following warning once 5,000,000 "executed script statements" have occurred in one synchronous script execution (z. B. von einem Timeout oder von einem Ereignishandler).Was zählt als eine "ausgeführte Skript-Anweisung" für IE "Stop dieses Skript ausführen?" Warnungszähler?

Stop läuft dieses Skript? Ein Skript auf dieser Seite verursacht, dass Ihr Web Browser langsam ausgeführt wird. Wenn es weiterhin ausgeführt wird, reagiert Ihr Computer möglicherweise nicht mehr .

Ich versuche, einige komplexe, schwere Code zu optimieren, um diese Fehlermeldung zu vermeiden. Ich habe bereits den Standard-Ratschlag befolgt, der, wo möglich, den Code in separate asynchrone Brocken mit Dingen wie setTimeout() brechen soll. Ich kann nicht mehr davon machen, ohne Race Conditions zu erstellen, also suche ich den ganzen Code zu straffen, der oft passiert, z.B. innerhalb großer for Schleifen.

Um dies zu tun, Ich möchte verstehen, was genau IE als eine "ausgeführte Skript-Anweisung" zählt, so werde ich wissen, welche Optimierungen in meinen Schleifen den Unterschied machen und welche nicht.

Ich habe nach Standarddefinitionen von "ausgeführten Skriptanweisungen" gesucht, ohne Erfolg - die meiste Zeit wird "Skriptanweisung" verwendet, es scheint sich auf den Inhalt eines html <script> Tags zu beziehen, was eindeutig eine andere Richtung der Begriff. Die Definition ist hilfreich, lässt aber einige Zweifel darüber, wie sie gezählt werden (siehe Beispiele unten).

Here's what Microsoft have to say on the matter (Ich habe hinzugefügt Absatzumbrüche zur besseren Lesbarkeit):

Ab Internet Explorer 4.0 und späteren Versionen, ist die Time-out nicht mehr ein fester Wert, basierend auf Windows-Meldungen. Internet Explorer verfolgt nun die Gesamtzahl der ausgeführten Skriptanweisungen und setzt den Wert jedes Mal zurück, wenn eine neue Skriptausführung gestartet wird, z. B. von einem Zeitlimit oder einem Ereignishandler für die aktuelle Seite mit der Skript-Engine.

Internet Explorer zeigt ein Dialogfeld "Skript mit langer Laufzeit" an, wenn dieser Wert über einem Schwellenwert liegt.

Der Internet Explorer überprüft nicht bei jeder Anweisung, ob der Wert überschritten ist. Periodisch fragt das Skriptmodul Internet Explorer mit der Anzahl der ausgeführten Anweisungen ab, und Internet Explorer prüft, ob das Limit überschritten ist. Aufgrund dieses Mechanismus ist es möglich, mehr als das Standardlimit ohne das Dialogfeld auszuführen, wenn die gesamte Skriptausführung abgeschlossen ist, bevor das Skriptmodul Internet Explorer abfragt.

einige einfache Beispiele zu geben, die mir zweideutig scheinen:

  1. Would var a = 1, b = 2, c = 3; zählen als ein „ausgeführt Skript-Anweisung“ und var a = 1; var b = 2; var c = 3; zählen als drei? Oder wären beide drei?
  2. Would if(someFunction()){} (keine Aussagen innerhalb someFunction() sein, eine Aussage zu zählen, oder zwei (ein Anruf plus eine bedingte)?
  3. Ist if(a){}else{} eine bedingte Anweisung oder zwei? Wenn man, if(a){}else if(b){}if(a==b||(c&&a==c&&c==d)){} ein
  4. Ist zwei? Würde , zwei, drei, vier, fünf Aussagen (oder mehr?)?Ich bin mir bewusst, dass alles wie if(a){} eine Javascript-Funktion aufruft, um in boolean zu konvertieren - würde dies zusätzliche Aussagen zusätzlich zu den Vergleichen hinzufügen?
  5. Würde var value = someFunction(); if(value){} drei sein, da es eine Zuweisung hinzufügt, oder würde der Funktionsaufruf als Teil der Zuweisungsanweisung gezählt werden?
  6. Was ist mit Verkettung? Zum Beispiel, wenn jQuery verwendet wird, dann (ohne die ausgeführten Skriptanweisungen innerhalb von jede Funktion) ist die Zeile $(selector).show().css(obj).appendTo($el); eine "Skriptanweisung ausgeführt", oder vier? Ich würde mir vorstellen, es wären vier "Call" -Aussagen.
  7. Vermutlich würde var $someEl = $(selector).show().css(obj).appendTo($el); dies auf fünf Aussagen erhöhen - vier Anrufe plus eine Zuweisung? (IE würde zählt nicht nur als eine Zuweisungsanweisung und weitermachen?)

Natürlich ist diese einfachen Beispiele oben sind kleine Fische - ich versuche, „den Feind kennen“ hier in der Lage zu sein, zu beurteilen, wie sie am besten um komplexe Schleifen zu optimieren.

Ich bin entweder für eine Faustregel oder einige suchen erklärt Beispiele wie die oben

+0

kann ich definitiv nicht sagen, aber 'var whatever' zählt fast sicher nicht, da die Anweisung zur Laufzeit nicht ausgeführt wird. Davon abgesehen ist es wahrscheinlich, dass eine Zeile Code ausgeführt wird, sei es if (foo) {'oder Ihre lange jQuery-Kette am Ende. Die jQuery-Kette führt jedoch wahrscheinlich einige hundert Codezeilen aus der jQuery-Bibliothek aus. Mit anderen Worten, # 1 ist 0, # 5 ist 2 (getrennt durch das Semikolon), alle anderen sind 1. Aber Sie müssen den Codepfaden folgen, um zu sehen, wie viel Code tatsächlich in # 2, # 5 ausgeführt wird. # 6, # 7 –

Antwort

0

Zu meinem Verständnis Browser Ausführen von Code aus einer Warteschlange.

Wenn Code ausgeführt wird und Sie ein setTimeout() erstellen, wird der Code nicht parallel mit anderem JavaScript-Code ausgeführt, selbst wenn Sie das Zeitlimit auf 4 Millisekunden setzen (jeder Browser kann unterschiedlich sein, kein Kommentar unten) der Browser. Stattdessen wird die Funktion in eine Warteschlange eingereiht.

Wenn das aktuell ausgeführte Skript beendet ist, sucht es in der Warteschlange nach dem nächsten auszuführenden Element. Die Warteschlange könnte Event-Handler (von Benutzereingaben, obwohl ich denke, dass sie priorisiert werden können, nicht sicher) und Dinge wie Ajax Call-Antworten (wie jQuery Ajax Anruf Erfolg Code usw.), sie alle hinzugefügt werden die Warteschlange und sie werden ausgeführt zu einer Zeit.

JavaScript läuft immer in einem einzigen Thread, es gibt nie zwei Threads, die JavaScript-Code parallel ausführen. Dieser eine Thread nimmt Material aus der Warteschlange und führt eines nach dem anderen aus.

Hinweis: Es ist besser, die Dinge nicht in großen for-Schleifen auszuführen, da dies die Fehler auslöst, die Sie bekommen.

+0

setTimeout von 0 hat gemischte Ergebnisse. Es lief früher in einigen Browsern, aber ich kann mich nicht erinnern, von Anfang an. Also ein Timeout von 1 ist sicherer (und verhält sich in den meisten Browsern genauso) –

+0

@zyklus Ich dachte, dass alle Browser setTimeout (func, 0) in setTimeout (func, 4) oder jetzt standardmäßig größer machen (dh es gibt ein Mindestuntergrenze, die sie unterstützen werden) Sie können jedoch Recht haben, und ich kann sehen, warum es klug wäre, das zu tun (besonders wenn wir nicht wirklich wissen, wie jeder und jeder Browser damit umgeht.) Netter Punkt! – jwwishart

+0

Die meisten Browser tun das, aber wie ich schon sagte, benutzten einige Browser 'setTimeout (func, 0)' als 'func()'. Und sie "ändern" es nicht zu einem "4ms", "10ms", egal welcher Timer, es ist nur, dass das der Flush-Zyklus dieser Browser ist. Wenn Sie einen Browser mit einem 10ms Flush haben und einen setTimeout mit 1ms zu Beginn des Zyklus ausführen, wird es 10ms später ausgeführt. Wenn Sie jedoch zuerst 9ms CPU-Zeit verbrauchen, läuft es 1ms später. –

2

Was Sie fragen, kann nur erraten werden, es sei denn irgendein Microsoft IE8 Entwickler kommt und beantwortet Ihre Frage.
eine schwächliche Froggy ohne Verbindungen mit Microsoft Sein auch immer, entwarf ich einen einfachen Test, um zu versuchen und zu messen, wie Aussagen gezählt:

<body> 
<div id='div'></div> 
<script> 
var count = 5000000; 
var res = 0; 
var d = document.getElementById ('div'); 
function fun (aaa) // 1 statement 
{ 
    aaa+= Math.random(); // 1 statement 
    aaa+= Math.random(); // 1 statement 
    aaa+= Math.random(); // 1 statement 
} 
function format (count) // 1 statement 
{ 
    return Math.round(count*100/i)/100; // 1 statement 
} 
function format2 (count) // 1 statement 
{ 
    var a = count*100; //4 statements 
    var b = a/i; 
    var c = Math.round (b); 
    var d = c/100; 
    return d; // 1 statement 
} 

for (var i = 0 ; i != count ; i++) // 2 statements 
{ 
    res += Math.random();      // 1 statement 
    d.innerHTML = format2(count);    // 1 statement 
    d.innerHTML = Math.round(count*100/i)/100; // 1 statement 
    fun (res);         // 1 statement 
} 
</script> 
</body> 

ich dieses Skript auf IE8 über XP in einer VirtualBox lief.

Die auf der Seite angezeigte Zahl entspricht ungefähr der Anzahl der Anweisungen pro Schleife (IE zählt sie). Die Ungenauigkeit ist wahrscheinlich auf die asynchrone Abfrage der Anzahl der Anweisungen zurückzuführen, wie im Microsoft-Dokument erläutert.

Sie können den Code ändern, um selbst zu sehen, welche Art von Anweisungen als Anweisungen gezählt werden.

Meine empirischen Beobachtungen bisher:

Es eine Erklärung scheint in der Tat nahe der grammatische Definition, das heißt alles bis zum nächsten ; gefunden.

  • eine Schleife zählt als 2-Anweisungen (die Probe und das indice Update, wahrscheinlich)
  • ein Funktionsaufruf zählt als 2-Anweisungen, unabhängig von dem Ergebnis einer Variablen
  • eine beliebig komplexe Ausdrucksauswertung beeinflußt wird zählt als eine einzige Anweisung
  • Built-in-Funktionen zählen nicht als Anweisungen, aber jede Anweisung in benutzerdefinierten ausgeführt wird.

Es scheint, dass Sie innerhalb der 5M Aussagen von Verpackungs Berechnungen in komplexere Einzel Aussagen erlaubt mehr Leistung stopfen konnte.

All dies gesagt, ein Design, das einen Browser verwendet, um schwere Berechnungen durchzuführen ist grundlegend fehlerhaft, wenn Sie mich fragen.

Verwandte Themen