20

Ich habe für sie bisher etwa 5 experimentelle Sprachen und Dolmetscher entworfen, für Bildung, als Hobby und zum Spaß.Interpretierte Sprachen: Je höher der Level, desto schneller?

Eines ist mir aufgefallen: Die Assembler-ähnliche Sprache, die nur Subroutinen und bedingte Sprünge als Strukturen enthält, war viel langsamer als die Hochsprache mit if, while und so weiter. Ich entwickelte sie beide gleichzeitig und beide wurden Sprachen interpretiert. Ich habe die Interpreter in C++ geschrieben und versucht, den Code-Ausführungsteil so schnell wie möglich zu optimieren.

Meine Hypothese: In fast allen Fällen steigt die Leistung der interpretierten Sprachen mit ihrem Niveau (hoch/niedrig).

  • Bin ich im Grunde richtig mit diesem?

EDIT (Wenn nicht, warum?): Ich kann nicht das Wort zusammengestellt erwähnt habe hier noch einmal, es ist etwa im Vergleich zu interpretieren interpretiert!

+13

Geez, tun so viele Leute nicht die Frage hier lesen? meine Güte. OP vergleicht nicht mit kompilierten Sprachen. OP vergleicht hochrangige interpretierte Sprachen mit niederrangigen INTERPRETIERTEN Sprachen .... –

+2

@Brian: Wie die folgende Diskussion zeigt, ist die Unterscheidung zwischen * kompiliert * und * interpretiert * offenbar nicht so eindeutig, wie es auf den ersten Blick scheinen mag . –

+0

@Robert: Wie so? Eine kompilierte Sprache ist eine Sprache, die zur Assembly der Maschine kompiliert wird, auf der sie ausgeführt wird. Eine interpretierte Sprache ist eine Sprache, die einem Interpreter zugeführt wird und in einer Art virtueller Maschine läuft. Java ist weder. Java wird in eine intermediierte Sprache übersetzt. –

Antwort

4

Die Realität ist natürlich etwas komplizierter. Wenn Sprachen, Interpreter und Compiler ausgefeilter werden, ergeben sich für die Maschine neue Möglichkeiten zur Optimierung der Leistung. Außerdem hängt die Leistung eines gegebenen Programms stark von der Qualität des Codes ab, den der Programmierer geschrieben hat.

Die Leistung wirkt sich auch auf verschiedene Arten von Programmen unterschiedlich aus. So nehmen Branchenanwendungen zum Beispiel fast immer den größten Teil ihrer Schnelligkeit ein, wenn sie Daten aus einer Datenbank nachschlagen und über die Leitung senden, während Spieleprogrammierer sich mit einem völlig anderen Leistungskonzept befassen müssen, nämlich dem Grafikkartenrahmen Raten.

So ist das Leistungsbild nicht annähernd so einfach wie es scheint.

+2

Es ist erwähnenswert, dass er sagt, dass seine höher interpretierte Sprache schneller ist als seine * interpretierte * Sprache, * nicht * dass sie schneller ist als kompilierter Code. Während die Punkte, die Sie machen, absolut gültig sind, glaube ich nicht, dass er das vorschlägt. –

+0

@Adam: Ja, das habe ich gesehen. Wer hat von einer * interpretierten Assemblersprache gehört? * –

+0

@Robert Harvey: Ich brauchte etwas, mit dem ich einfach anfangen konnte; D Es ist aber ziemlich schnell: ** Dreimal so schnell wie Python ** und fünfmal schneller als Ruby. (Gemessen mit verschiedenen Funktionsaufruf-, Rekursions-, Ganzzahlverarbeitung- und Zeichenfolgenmanipulationstests) – immersion

30

In beiden Fällen interferieren Sie den Code. Ich würde mir vorstellen, dass Sie in den höheren Programmiersprachen weniger Anweisungen haben, um die gleiche Aufgabe zu erledigen, so dass Sie weniger Zeit damit verbringen, Anweisungen zu interpretieren und mehr Zeit damit zu verbringen, etwas Nützliches zu tun.

+1

Ich würde vorschlagen, dass die OP-Profil-Interpretation sowohl von seinem hohen Niveau als auch von einer seiner Low-Level-Sprachen. Wenn dies der Grund (wahrscheinlich) ist, sollte es deutlich im Profil angezeigt werden. –

+0

@Martinho: Ich würde das gleiche erreichen, indem ich den Interpreter einzeln stecke. Ich kann sagen, wie viel Zeit es damit verschwendet, wie müde ich werde. –

+0

@Mike: genau das habe ich gesagt. Sie haben sich gerade einen Profiler geschnappt, den Sie in die Pedale treten müssen: P –

0

Zusammenfassung: Benchmarking ist schwer. Sie können nicht aus Anekdoten verallgemeinern.

Dies ist keine durch Beweise unterstützte Regel.

Wie richten Sie Ihr Experiment ein, aus dem Sie die Schlussfolgerung "höher = schneller" ziehen? Haben Sie Beispielimplementierungen von identischen Algorithmen und Testsätzen, mit denen Sie eine interpretierte Sprache gegen eine andere objektiv messen können?

Wenn Sie nur kleine Mini-Benchmarks erstellen, ist die Wahrscheinlichkeit sehr hoch, dass Sie aus zu wenigen Datenpunkten eine Schlussfolgerung ziehen.

Zum Beispiel, wenn eine interpretierte Sprache einen Operator quicksort hat, könnten Sie denken "Aha! Faster!" als eine Sprache, in der Sie die Sortierung manuell durchführen müssen. Quicksort hat jedoch die schlechteste Fallleistung von O (n^2). Wenn ich Ihre übergeordnete Operation ein Beispiel für einen Worst-Case-Datensatz übergebe, wird eine andere hand-implementierte merge sort es schlagen.

+0

Nun, Sie können immer noch mit interpretierten Sprachen optimieren. Beispiele: IronPython, IronRuby (und ich bin mir sicher, dass die C-Implementierungen auch eigene Optimierungen haben). Sie können auch "kompilieren wie Sie gehen", genauso wie ein JIT-Compiler mit Java-Bytecode oder CIL. –

+1

Diese Beispiele werden zu einem Byte-Code kompiliert (und vermutlich optimiert) und dann wird der Byte-Code interpretiert. – Joel

+0

@Joel: Ich folge nicht. Der Byte-Code * ist eine interpretierte Sprache * und erleidet * eine Optimierung * durch den Interpreter (auch bekannt als JIT-Compiler). Außerdem profitiert IronPython von Optimierungen, die vom DLR bereitgestellt werden, wie Call-Site-Caching. –

1

Nun, natürlich hängt es davon ab, wie Sie die verschiedenen Sprachen implementiert haben.

Ich würde vermuten, dass mehr Anweisungen interpretiert werden müssen, um das Gleiche in einer untergeordneten interpretierten Sprache zu tun, und es wird der Aufwand sein, jeden einzelnen Low-Level-Befehl im Gegensatz zu weniger höheren Level-Anweisungen zu interpretieren.

12

Am Ende wird das Parsen einer Textzeile in Ihrer Sprache ungefähr die gleiche Zeit in Anspruch nehmen, egal, ob es sich um Assemblierung im Vergleich zur nächsten großen Sprache (TNBL) handelt. Dies ist im wörtlichen Sinn nicht wahr, aber es ist in einer Art Turing-esque, Big-O-Notation wahr.

Wenn es (wieder "rund") nimmt die gleiche Menge an Zeit, um zu bestimmen, was das bedeutet:

mov $3, $4, $5 

wie folgt aus:

print "foo" 

... dann lassen Sie uns das Schreiben vorstellen Hallo Welt in unseren zwei Sprachen. Der Assembly Interpreter wird ein viel komplexeres Programm zum Parsen haben. Say, n Zeilen lang, das ist n mal so viele Zeilen wie die TNBL Hallo Wolrld. Also ist Ihr grundlegendster Overhead n mal so lang.

Darüber hinaus haben Sie den gesamten Code, den Sie in der einfacheren Sprache ausführen, die das Verhalten von Registern, Operationen usw. modelliert. Es ist eine Menge Arbeit. In TNBL gibt es fast eine Eins-zu-Eins-Zuordnung zwischen der Semantik des interpretierten Codes und etwas, das Sie in der Host-Sprache tun können. Dies bedeutet einen stark reduzierten Overhead beim Übergang von der Semantik zur Ausführung.

Ich bin sicher, Sie werden einige Java-Programmierer sehen, die diese These ablehnen würden, aber ich möchte darauf hinweisen, dass Java eine Reihe von Vorteilen hat: ein intermediärer Bytecode, der versucht, den Code so nahe wie möglich zu bekommen die Hardware, bevor sie ausgeführt wurde, und tausende von Mannjahren wurden in die Entwicklung der Kompilier- und Laufzeitoptimierung dieser Sprache investiert. Sie sind kaum auf dem Kontinuum mit einer Hobbysprache. =]

1

Ich würde sagen, Sie sind etwa halb richtig. Wenn Sie die Geschwindigkeit der Interpretation grafisch darstellen, mit dem Sprachlevel auf der X-Achse und der Ausführungsgeschwindigkeit auf der Y-Achse, erhalten Sie eine "Badewannen" -Kurve - die Interpretation einer extrem niedrigen Sprache kann ziemlich schnell sein und eine extrem hohe interpretieren Level-Sprache kann ziemlich schnell sein. Dazwischen ist die Interpretation wesentlich langsamer.

Angesichts einer extrem hohen Eingabesprache (z. B. APL) erhalten Sie einen minimalen Overhead für die Interpretation, da Sie aufgrund der Analyse relativ wenig Eingabecodes viel Arbeit erledigen können.

Im gegenteiligen Extrem kann man ziemlich gute Geschwindigkeit erreichen, einfach weil die Interpretation mit einer ausreichend niedrigen Sprache fast trivial wird. Der innere Interpret einer Forth-Implementierung ist ein Paradebeispiel dafür. Diese stellen oft ein gegebenes Programm ziemlich kompakt dar, was tendenziell ziemlich cachefreundlich ist, so dass man zumindest in der Theorie eine Ausführung erreichen könnte, die so schnell (oder sogar etwas schneller) ist als reiner Maschinencode.

Die ursprüngliche Absicht war, dass die meisten JVMs, die .NET "gemanagte" Umgebung, Smalltalk-Bytecode-Interpreter usw. zu dem letzteren Fall passen würden. Wie die meisten, die versucht haben, diese zu entwickeln, schnell gefunden haben, ist es hart, um den Dolmetschaufwand niedrig genug zu halten, um dies zu erreichen. Jeder, den ich kenne, der in diese Klasse passt, hat die innere Schleife in Assemblersprache von Hand geschrieben und normalerweise von einem guten Assemblerprogrammierer.Ich würde fast so weit gehen zu sagen, dass, wenn Sie versuchen, eine höhere Sprache (sogar C) zu verwenden, es langsamer sein wird, und wahrscheinlich auch erheblich (wenn Sie zusätzlich alle Eingabeanweisung hinzufügen, sogar eine zusätzliche Anweisung in der inneren Schleife wird fast sicher zu einer messbaren Geschwindigkeitsstrafe führen).

0

Wie machen Sie einen fairen Vergleich?

Ich nehme an, Sie zählen nicht Parsing-Geschwindigkeit, und ich nehme an, dass Sie eine Zwischen-Byte-Code-Befehlssatz generieren, und das ist, was Sie interpretieren.

Angenommen, Sie haben einen "Benchmark", bei dem es sich um eine Schleife handelt, die die Elemente eines Arrays summiert. Wenn Ihre übergeordnete Sprache spezielle Bytecode-Anweisungen dafür hat, so dass in der höheren Sprache weniger Bytecodes zu interpretieren sind, würde das genau dort erklären, warum es schneller ist.

0

Angenommen, beide werden auf die gleiche Weise implementiert, wobei die Sprache der unteren Ebene nicht optimiert ist und die Sprache der höheren Ebene nicht auf die untere Ebene des Zwischencodes erweitert wird - "wahrscheinlich".

In solch einem Fall hätte die Hochsprache den Vorteil, mehr kompilierten (schnelleren) Code pro Anweisung zu stopfen.

In der Praxis sollte jedoch eine interpretierte Sprache auf niedriger Ebene in der Lage sein, den Overhead pro Anweisung zu reduzieren, und ist in der Regel viel einfacher zu implementieren JIT-Kompilierung mit. Wie gut sie implementiert sind, wird letztlich bestimmen, wie sie aufeinander stapeln.

Ich werde sagen, dass es einfacher ist, um eine schnellere Hochsprache zu implementieren. (in meiner begrenzten Erfahrung)

1

Wenn Sie eine interpretierte Sprache mit einem Befehl hatten: runMyEntireProgramNatively(), wäre es schneller als eine interpretierte Sprache mit mehr Befehlen. Je weniger ein Befehl ausgeführt wird, desto größer ist das Verhältnis zwischen der Zeit, die für die Interpretation aufgewendet wird, und der tatsächlichen Ausführung des Vorgangs.

Verwandte Themen