Größenbeschränkung für Browser-Javascript-Stapel

75

Ich bekomme einige clientseitige Probleme mit dem Überlauf von Javascript-Stapeln speziell im IE-Browser. Dies geschieht in einer Bibliothek eines Drittanbieters, die einige Funktionsaufrufe ausführt, und aus irgendeinem Grund bremsen sie gelegentlich im IE nur aufgrund des niedrigen Stapellimits.

Ich habe dann einen kleinen Test-HTML-Code codiert, um die Stapelgrößenbeschränkung für einige Browser zu testen, und festgestellt, dass IE8 im Vergleich zu FF 7 oder Chrome 14, die auf einem Laptop mit Windows 7-Betriebssystem und 8 GB RAM ausgeführt werden, tatsächlich eine kleine Stapelbeschränkung aufweist:

<html>
<body>

<!-- begin Script: -->
<script type="text/javascript">

function doSomething(){

  var i = 3200;
  doSomethingElse(i);

}

function doSomethingElse(i){
  if (i == 0) return -1;
  doSomethingElse(i-1);
}

doSomething(); 

</script>
<!-- END OF PAGE -->

</body>
</html>

IE erhöht den Stapelüberlauf, wenn die Werte bei 3200 liegen. Firefox und Chrome können im Vergleich zum IE eine sehr tiefe Rekursion verarbeiten.

Ich würde gerne wissen, ob es eine Möglichkeit gibt, die Stack-Overflow-Ausnahme mit der Javascript-Funktion zu verknüpfen, die sie zur Laufzeit im IE oder einem anderen Browser ausgelöst hat, und ob sie den Stacktrace mit der Funktionskette im Stack im Moment geben könnte Fehler wurde ausgelöst.

guilhebl
quelle
2
3200 Aufrufe sind viel Stapelspeicher. Python-Programmierer (also diejenigen, die nicht darauf aus sind, rekursive Abstiegsparser zu schreiben oder ganz einfache Schleifen durch Rekursion zu ersetzen) kommen mit einem Limit von 1000 Aufrufen gut zurecht. Was machst du?
4
Es ist nicht fragend formuliert, aber der letzte Satz "Ich frage mich, ob es ... gibt" könnte mit "Sind da" beginnen und mit einem Fragezeichen enden, was eine ziemlich direkte Frage ergibt.
Jball
Vielen Dank für das Feedback, ich werde die Frage besser klären
Guilhebl

Antworten:

128

Mit einem einfachen Test :

var i=0;
function inc() {
    i++;
    inc();
}
inc();

Internet Explorer

  • IE6: 1130
  • IE7: 2553
  • IE8: 1475
  • IE9: 20678
  • IE10: 20677

Mozilla Firefox

  • 3,6: 3000
  • 4,0: 9015
  • 5,0: 9015
  • 6,0: 9015
  • 7,0: 65533
  • 8b3: 63485
  • 17: 50762
  • 18: 52596
  • 19: 52458
  • 42: 281810

Google Chrome

  • 14: 26177
  • 15: 26168
  • 16: 26166
  • 25: 25090
  • 47: 20878
  • 51: 41753

Safari

  • 4: 52426
  • 5: 65534
  • 9: 63444

Oper

  • 10.10: 9999
  • 10.62: 32631
  • 11: 32631
  • 12: 32631

Verwenden Sie in Bezug auf Ihre Frage die Entwicklertools Ihres Browsers, um den Stapel anzuzeigen. F12Klicken Sie in IE 8+ auf , gehen Sie zur Registerkarte Skript und klicken Sie auf Debugging starten. Es wird unterbrochen, wenn eine Ausnahme ausgelöst wird, und Sie können den Aufrufstapel sehen. Sie können auch die Entwicklertools von Chrome verwenden, Ctrl+ Shift+ J.

josh3736
quelle
7
Sie können F12 auch für Chrome verwenden
Juan Mendes
1
Mit dem Test jsfiddle.net/9YMDF/show habe ich ~ 21000 für Chrome 28, 26000..53000 für Firefox 20+ und ~ 3000 für IE10 unter Windows 7 SP1 64-Bit. Opera 12.X hat eine Stapeltiefe nahe 32768. Und ich habe eine unglückliche IE8-Installation mit einer Stapeltiefe von 276 gefunden!
Victor
Sie können diese Ergebnisse mit dem hier verlinkten BrowserScope
Janus Troelsen
Dies gibt mir 151102 auf Microsoft Edge, während auf IE11 seine 54375!
Gaurav Ojha
5
Ich denke, dass die Nummern nicht dem Browser zugeordnet sind, sondern dem Speicher, der derzeit von der Anwendung reserviert wird. Aus diesem Grund variieren die Antworten stark. Zum Beispiel habe ich gerade diesen Test durchgeführt und bekomme 20922 für Chrome 56 (mit vielen Erweiterungen) und 8921 für einen eher einfachen Vanille-Firefox 49. Mit einem absolut serienmäßigen Browser bekomme ich 16615.
roberto tomás
7

Dies ist browserspezifisch, nicht nur die Stapelgröße, sondern auch Optimierungen, wie die Optimierung der Schwanzrekursion und so weiter. Ich denke, die einzig verlässliche Sache hier ist, auf eine Weise zu codieren, die nicht Unmengen von Dingen in den Stapel legt, oder jeden Browser manuell zu testen (tief in die Dokumentation zu lesen). Wenn Sie den Fehler "zu viel Rekursion" oder ähnliches sehen, wissen Sie bereits, dass mit Ihrem Code etwas wirklich nicht stimmt.

Nikoloff
quelle
Ist TCO wirklich in JavaScript erledigt? Ich habe gelesen, dass ES6 möglicherweise Unterstützung erhält, aber ich glaube nicht, dass es bereits implementiert wurde.
Janus Troelsen
TCO steht derzeit hinter einem Flag in Chrome (zwei verschiedene Implementierungen werden evaluiert). Mir sind keine Browser bekannt, in denen dies standardmäßig implementiert ist.
Jethro Larson
1
@ JanusTroelsen: ES2015 ("ES6") erfordert in der Tat Motoren, um TCO zu machen. V8 hat es, aber das V8-Team hält es noch nicht für "stabil", daher müssen Sie es aktivieren. (V8 klassifiziert Funktionen, die sie überhaupt gestartet haben, als "Versand" [erledigt], "stabil" und "in Bearbeitung". Die Gesamtbetriebskosten bleiben "in Bearbeitung", aber die Grundlagen sind für alle drei Codegeneratoren von V8 vorhanden. Ich denke, sie Ich habe es noch nicht auf "stabil" hochgestuft, da sie noch optimiert / fehlerhaft / fehlerbehebend sind. Mehr hier: stackoverflow.com/a/30369729/157247 )
TJ Crowder
Derzeit ist Safari nur Browser mit korrekten TCO
ridderhoff
Ein Anwendungsfall, um Tonnen von Material auf den Stapel zu legen array1.push(...array2), ist viel schneller als array1 = array1.concat(array2)"maximale Stapelgröße überschritten", wenn Array2 zu lang ist. siehe hier
Mila Nautikus