Nach einigen erneuten Tests habe ich festgestellt, dass meine Implementierung nicht sehr viel Rekursion verarbeiten kann. Obwohl ich nach einigen Tests in Firefox festgestellt habe, dass dies häufiger vorkommt als ursprünglich angenommen. Ich glaube, dass das grundlegende Problem ist, dass meine Implementierung 3 Aufrufe benötigt, um einen Funktionsaufruf zu tätigen. Der erste Aufruf erfolgt an eine Methode mit dem Namen Call
, die sicherstellt, dass der Aufruf an ein aufrufbares Objekt erfolgt und den Wert aller Argumente bezieht, die Referenzen sind. Der zweite Aufruf erfolgt an eine Methode mit dem Namen Call
, die in der Schnittstelle ICallable
definiert ist. Diese Methode erstellt den neuen Ausführungskontext und erstellt den Lambda-Ausdruck, wenn er nicht erstellt wurde. Der letzte Aufruf erfolgt an das Lambda, das das Funktionsobjekt einkapselt. Es ist ziemlich schwer, einen Funktionsaufruf zu machen, aber ich bin mir sicher, dass ich mit ein wenig Optimierung die Rekursion zu einem brauchbaren Werkzeug machen kann, wenn ich diese Implementierung verwende.Wie kann ich die Rekursionsfähigkeiten meiner ECMAScript-Implementierung verbessern?
5
A
Antwort
2
Ich kann nicht glauben, wie einfach das zu arbeiten war. Grundsätzlich überprüfe ich in meinem Compiler, ob die Funktion das Ergebnis des Aufrufs selbst zurückgibt. Wenn dem so ist, gebe ich stattdessen die Argumente zurück, die übergeben werden. Dann greife ich einfach irgendwelche Referenzwerte und lade das Hintergrundlambda erneut ein. Damit konnte ich Millionen von rekursiven Calls machen.
Ich möchte DrJokepu für die Inspiration dieser Lösung danken.
public object Call(object thisObject, object[] arguments)
{
var lexicalEnviroment = Scope.NewDeclarativeEnviroment();
var variableEnviroment = Scope.NewDeclarativeEnviroment();
var thisBinding = thisObject ?? Engine.GlobalEnviroment.GlobalObject;
var newContext = new ExecutionContext(Engine, lexicalEnviroment, variableEnviroment, thisBinding);
var result = default(object);
var callArgs = default(object[]);
Engine.EnterContext(newContext);
while (true)
{
result = Function.Value(newContext, arguments);
callArgs = result as object[];
if (callArgs == null)
{
break;
}
for (int i = 0; i < callArgs.Length; i++)
{
callArgs[i] = Reference.GetValue(callArgs[i]);
}
arguments = callArgs;
}
Engine.LeaveContext();
return result;
}
Verwandte Themen
- 1. Wie kann ich die subjektive Geschwindigkeit meiner Anwendung verbessern?
- 2. Wie kann ich dies verbessern?
- 3. Wie kann ich eine Reihe von Konstanten erstellen, um die Usability meiner Methoden zu verbessern?
- 4. Wie kann ich die Geschwindigkeit meiner Tabellenfilterung von JavaScript auf Smartphones verbessern?
- 5. Wie kann ich die Effizienz und/oder Leistung meiner relativ einfachen Java-Zählmethode verbessern?
- 6. Wie kann ich mein Suchskript verbessern?
- 7. Wie kann ich die URL in Laravel verbessern?
- 8. Wie kann ich die WMI-Leistung in .NET verbessern?
- 9. Wie kann ich diesen Code verbessern
- 10. Wie die SQL-Performance von meiner Java-Anwendung verbessern
- 11. Wie kann ich meine FileSaving verbessern?
- 12. Wie kann ich SQL Server verbessern Spiegelung
- 13. Wie kann ich diesen Mapping-Algorithmus verbessern
- 14. Wie kann ich meinen JS-Code verbessern?
- 15. Wie kann ich diesen Rails-Code verbessern?
- 16. Wie kann ich mein Palidrom-Programm verbessern?
- 17. Wie kann ich diesen Code verbessern?
- 18. Emacs: Wie kann ich Ido-Leistung verbessern?
- 19. Wie kann ich clisp Fehlermeldungen verbessern?
- 20. Wie kann ich diesen Sortiercode verbessern?
- 21. Wie kann ich diesen Algorithmus verbessern? (Bildverarbeitung)
- 22. Wie kann man die Golang-Übersetzungsgeschwindigkeit verbessern?
- 23. Wie kann man die Vec-Initialisierungszeit verbessern?
- 24. Wie kann ich diese endlose Abfrage verbessern?
- 25. Wie kann ich die WMI-Leistung mithilfe von Delphi verbessern?
- 26. Wie kann ich die Hibernate-Leistung in Java verbessern?
- 27. wie ich die Leistung in Jquery verbessern kann
- 28. Wie kann ich die Leistung des RichFaces ScrollableDataTable-Steuerelements verbessern?
- 29. Wie kann ich die Schleifenleistung bei Verwendung eines Projektmakros verbessern?
- 30. Wie kann ich die Fertigstellung des Eclipse-Codes verbessern?
Ich nehme an, Umwandlung von Tail-Rekursion in Schleifen ist für den Augenblick nicht im Fokus? Auf diese Weise könnten Sie vermeiden, vollständig anzurufen. –
@DrJokepu - Ich habe die Idee der Schwanzrekursion in meinem Hinterkopf behalten, aber ich suche auch nach Vorschlägen, wie man die Anrufe selbst als eine allgemeine Leistungsverbesserung weniger schwer macht. Ich glaube auch nicht, dass die Tail-Rekursion in Fällen, in denen die Komplexität der Funktion zu groß ist, richtig implementiert werden kann. – ChaosPandion
Nun, es sieht nicht so aus, als würde es irgendetwas unnötig machen, hast du es mit einem Profiler versucht? Ich meine, Funktionsaufrufe (im Release-Modus) sind in CLR nicht sehr teuer (leider ist der zweite Call etwas zu fett, um vom JIT inline geschaltet zu werden), also bezweifle ich, dass das deshalb schwer ist. Vielleicht etwas in Reference.GetValue() oder etwas? Ein Profiler wäre definitiv sehr hilfreich. –