Sind Tail Call (TCO) von JavaScript-Engines optimiert?

91

Ich habe einen rekursiven Pfadfindungsalgorithmus, den ich in JavaScript implementiert habe, und möchte wissen, ob (alle?) Browser möglicherweise Ausnahmen für Stapelüberläufe erhalten.

Clofresh
quelle
2
Ist es tatsächlich ein rekursiver Algorithmus oder ein iterativer Algorithmus, der mit Rekursion implementiert wurde? Nach meinem Verständnis kann TCO nur bei letzterem helfen.
Nmichaels
1
Ich möchte nur hinzufügen, dass TCO keine onlyOptimierung ist. Die Unterstützung sollte Teil der Sprachspezifikation sein, nicht des Compilers / Interpreters, da Code, der gegen einen Interpreter / Compiler mit TCO geschrieben wurde, auf einem Interpreter / Compiler ohne TCO wahrscheinlich nicht funktionieren würde.
Hoffmann
1
Die aktuelle Unterstützung und die Entwicklung der Motoren finden Sie in der ES6-Kompatibilitätstabelle von Kangax hier: kangax.github.io/compat-table/es6/…
Roy Tinker

Antworten:

47

Die ECMAScript 4-Spezifikation sollte ursprünglich die TCO unterstützen, wurde jedoch gestrichen:

Keine Tail Calls mehr in JavaScript?

Soweit ich weiß, führen derzeit keine allgemein verfügbaren Implementierungen von JavaScript automatische Gesamtbetriebskosten durch. Dies kann Ihnen jedoch von Nutzen sein:

Tail Call-Optimierung

Im Wesentlichen wird durch Verwendung des Akkumulatormusters der gleiche Effekt erzielt.

Tim Sylvester
quelle
1
Nur zu Ihrer Information
Mark Porter
5
(Entschuldigung für das Trolling) ECMAScript 6 hat TCO (Proper Tail Calls) in die Spezifikation aufgenommen.
Frosty
@sclv: Was ist die Trampolinreferenz?
Bukzor
39
Das Akkumulatormuster erzielt nicht den gleichen Effekt wie die Gesamtbetriebskosten. Es transformiert lediglich rekursive Algorithmen in eine schwanzrekursive Form. Dies ist eine Voraussetzung dafür, dass TCO möglich ist, aber kein Ersatz dafür. Sie werden den Stapel immer noch in einer Sprache sprengen, die Tail-Calls nicht optimiert.
Marcelo Cantos
"Keine allgemein verfügbaren Implementierungen von JS führen derzeit automatische Gesamtbetriebskosten durch" Dies ist ab Knoten 6.2.0 falsch, wenn Sie das richtige Flag übergeben
Janus Troelsen
26

Momentan keine Freude, aber dankenswerterweise sind für Harmony (ECMAScript Version 6) die richtigen Tail Calls geplant. Http://wiki.ecmascript.org/doku.php?id=harmony:proper_tail_calls

Herr Sprecher
quelle
1
@MarkWilbur Die Frage betraf speziell Browser , nicht alle vorhandenen Implementierungen von ECMAScript.
Nutzloser Code
1
@UselessCode Nein, diese Frage betrifft "Javascript-Engines", also ... nicht nur Browser
BT
1
@BT Es gibt in der Tat viele JS-Umgebungen ohne Browser, und der Titel verwendet die allgemeineren "Javascript-Engines", aber der Hauptteil der Frage gibt an "... möchte wissen, ob (alle?) Browser möglicherweise einen Stack erhalten würden Überlaufausnahmen. "
Nutzloser Code
Ich muss kontern "aber der Titel sagt ...". Ich denke, weil er beide erwähnt, geht es um beide. Aber Sie haben Recht, wenn Sie sagen, dass die Antwort dadurch nicht obsolet wird.
BT
4
@MarkWilbur Soweit mir bekannt ist, verwendet Node die gleiche Version von v8 wie Chrome - die derzeit keine TCO-Unterstützung unterstützt. Ich hatte ein Problem mit dem JS und dem optimierten Assembler, den das aktuelle V8 produziert - gist.github.com/mcfedr / 832e3553964a014621d5
mcfedr
12

So ziemlich jeder Browser, dem Sie begegnen, wird "zu viel Rekursion" anzeigen. Hier ist ein Eintrag im V8-Bug-Tracker , der wahrscheinlich interessant zu lesen sein wird.

Wenn es sich um eine einfache Selbstrekursion handelt, lohnt es sich wahrscheinlich, eine explizite Iteration zu verwenden, anstatt auf die Beseitigung von Tail-Calls zu hoffen.

Hank Gay
quelle
Der Fehler wurde endlich akzeptiert. Es steht unter dem Epos "Feature Request Harmony". Hoffentlich bedeutet dies, dass sie planen, es zur ES6-Unterstützung in V8 hinzuzufügen.
Txangel
Sie können hier im Internet Explorer für die TCO-Unterstützung stimmen: wpdev.uservoice.com/forums/257854-internet-explorer-platform/…
Roy Tinker
12

Die Tail Call-Optimierung wird zukünftig im strengen ECMAScript 6-Modus unterstützt. Weitere Informationen finden Sie unter http://www.2ality.com/2015/06/tail-call-optimization.html .

Unter http://kangax.github.io/compat-table/es6/ finden Sie aktuelle Motorunterstützung.

Derzeit (18-07-2019) unterstützen die folgenden Engines die Tail Call-Optimierung:

  • Safari> = 10
  • iOS> = 10
  • Kinoma XS6
  • Duktape 2.3

Unterstützung, wenn das Flag "Experimentelle JavaScript-Funktionen" aktiviert ist:

  • Knoten 6.5
  • Chrome 54 / Opera 41 Die aktuelle Version der kompatiblen Tabelle listet sie nicht mehr auf
Simon Zyx
quelle
3

Die Tail Call-Optimierung ist jetzt in LispyScript verfügbar , das in JavaScript kompiliert wird. Sie können mehr darüber lesen Sie hier .

Santosh
quelle
Was ist mit gegenseitiger Rekursion?
Katze
2

Derzeit erkennen keine JavaScript-Implementierungen die Schwanzrekursion. In ECMAScript 6 werden Änderungen vorgenommen , und wie andere bereits gesagt haben, gibt es für V8 ein offenes Ticket .

Hier sehen Sie den von V8 generierten Assembler für eine Schwanzrekursionsfunktion:

Beispiel dafür, wie V8 die Rekursion kompiliert

Vergleichen Sie das damit, wie Clang dieselbe Funktion in C kompiliert hat

Beispiel für eine C-Compiler-Schwanzrekursion

V8 behält den rekursiven Aufruf bei, während der C-Compiler die Endrekursion erkannt und in eine Schleife geändert hat.

mcfedr
quelle
"Derzeit erkennen keine JS-Implementierungen die Schwanzrekursion." Das ist ab Knoten 6.2.0 falsch, aber Sie müssen eine Flagge übergeben
Janus Troelsen