Wie wird der Typ in einem dynamischen Sprachinterpreter / Compiler wie JavaScript überprüft?

11

In dynamischen Sprachen wie JavaScript oder Python wird der Typ einer Variablen zur Laufzeit festgelegt. Dies ist ein Grund, warum sie langsamer sind als typisierte Sprachen wie Java.

Wie wird die Typprüfung durchgeführt? Was ist der wesentliche Grund, warum dieser Prozess langsam ist?


quelle
Sie sind nicht langsamer, weil sie dynamisch sind, sie sind langsamer, weil es schwieriger ist, sie schneller zu machen. JavaScript ist eigentlich das am besten optimierte und ist ziemlich schnell.
Derek Litz

Antworten:

5

Die Frage ist verwirrend.

Es wird davon ausgegangen, dass die Typprüfung langsam ist, was nicht unbedingt der Fall ist.

Die Frage scheint auch den Prozess des Typversands mit der Typprüfung zu verwechseln , und es handelt sich um zwei verschiedene Dinge. Einer ist ein Prozess, der zur Laufzeit ausgeführt wird, der andere ein Prozess zur Kompilierungszeit. Ich vermute, die Frage ist wirklich nach Typ Versand.

Es ist der Typversand, der zur Laufzeit Overhead verursachen kann, da die Berechnung Zeit mit Anweisungen verbringt, die dynamisch entscheiden, welche Aktion basierend auf den zur Laufzeit angezeigten Wertetypen ausgeführt werden soll. Wenn ich beispielsweise in einer dynamischen Sprache "+" auf zwei Dinge anwende, kann dies numerische Addition oder Verkettung von Zeichenfolgen bedeuten. Daher muss ich Zeit damit verbringen, zu prüfen, was zur Hand ist, um zu entscheiden, was zu tun ist. Es gibt Bewertungsstrategien, mit denen die Kosten für den dynamischen Versand gesenkt werden können. (zB JITs verfolgen)

Informationen zur Typprüfung in JavaScript finden Sie unter: http://www.cs.brown.edu/~sk/Publications/Papers/Published/gsk-flow-typing-theory/ . Für einen allgemeineren Überblick über die Funktionsweise von Typprüfern werden die Algorithmen in einem Standardlehrbuch für Programmiersprachen behandelt. Zum Beispiel http://www.cs.brown.edu/~sk/Publications/Books/ProgLangs/

dyoo
quelle
Ich habe auch eine kleine Umfrage über die Verfolgung von JITs und dynamischen Sprachen in hashcollision.org/comprehensive/tracing.pdf
Der Javascript-Interpreter enthält Tag-Bits mit jedem Wert für den Typversand. Könnten Sie das etwas näher erläutern? Was ist zum Beispiel die Verwendung von Tag-Bits? Entspricht ein Bit einem Typ?
Das Konzept eines Typs ist nicht immer mit Repräsentation verbunden. Wir haben beispielsweise das Konzept eines "Meile" -Typs gegenüber einem "Kilometer" -Typ, und es ist sinnvoll, eine Sprache zu haben, die beim Kompilieren statisch erkennt, ob Berechnungen Operationen auf Werte, die die Typen durcheinander bringen, nicht ordnungsgemäß anwenden . Sie können sich vorstellen, dass sie dieselbe Darstellung haben, und wenn der Compiler zum Zeitpunkt der Kompilierung garantieren kann, dass sie niemals gemischt werden, gibt es keinen Grund, warum die Werte die zusätzliche Beschriftung in der Darstellung benötigen würden.
1
Fortsetzung: Vor allem in dynamischen Sprachen möchten Sie jedoch häufig Werte unterschiedlicher Typen darstellen. Es gibt verschiedene Möglichkeiten, diese Diskriminierung durchzuführen. Typ-Tags sind üblich, es gibt jedoch auch andere Techniken. Beispielsweise können Sie bestimmte Typen in blockierten Speicherbereichen platzieren. Siehe "Darstellen von Typinformationen in dynamisch typisierten Sprachen". lambda-the-ultimate.org/node/3912 für einen umfassenden Überblick über Darstellungstechniken.
7

Im Grunde genommen verweist in untypisierten Sprachen jeder Verweis auf ein Objekt, das sowohl den Typ als auch den Wert enthält. Zeigt beispielsweise var a = 3auf eine Instanz, die den Wert 3 und den Typ int enthält. Wenn Sie dies tun a = "bla", wird der Verweis auf eine Instanz aktualisiert, die die Zeichenfolge "bla" und die Typzeichenfolge enthält. Das alte Objekt wird verworfen.

Dies ist langsam, da jedes Mal, wenn eine Operation (z. B. a + b) für diesen Basistyp ausgeführt werden muss , die Laufzeit zuerst die Objekte dereferenzieren, prüfen muss, ob ihr Typ kompatibel ist, die Operation ausführen und ein neues Objekt erstellen muss.

Im Gegensatz dazu werden a + bin C ++ oder Java zur Kompilierungszeit überprüft , ob die Typen gültig und kompatibel sind. Dann werden a und b als unmittelbare Werte (keine Referenzen) gespeichert, und das Hinzufügen ist eine einfache Prozessoroperation für diese Werte.

Das ist natürlich alles sehr theoretisch. In der Praxis kann dieser Prozess stark optimiert werden, um den größten Teil des Overheads zu vermeiden, und dynamisch typisierte Sprachen können sehr schnell werden.

Solendil
quelle
1
Tricks wie polymorphe Inline-Caches können die Leistung erheblich verbessern. Die Schriften von David Ungar (Self) und Eliot Miranda (Squeak, Visual Works Smalltalk Virtual Machines) sind hinsichtlich der dynamischen Sprachleistung am informativsten.
Frank Shearar
0

Jeder Wert wird zusammen mit seinem Typ gespeichert, den man zuerst überprüfen muss. Auch Konvertierungen sagen, von Zeichenfolge zu Nummer gehen per Inspektion, im laufenden Betrieb.

Joop Eggen
quelle
Ja, das ist es, es ist nur eine Laufzeitprüfung, nichts Besonderes.
Anon