Wie schnell ist TorbScript?

Sechs bekannte Programme, jedes in TorbScript, C, Python und JavaScript, jede Nacht auf derselben Maschine gemessen - ein mit torb build gebautes TorbScript-Programm gegen C, und torb run gegen Python und Node.js.

TorbScript führt ein Programm auf zwei Arten aus. torb build macht daraus eine eigene Programmdatei, über C und einen C-Compiler. torb run startet es sofort, in der VM - einem Interpreter in torb, der keinen Compiler braucht.

Diese Seite misst beides. Die Programme sind sechs aus dem Computer Language Benchmarks Game, der Sammlung, mit der man Sprachen vergleicht, und jedes läuft gegen dasselbe Programm in C, Python und JavaScript.

Noch ist nichts gemessen. Die Zahlen kommen vom Linux-Runner der Forge, der die Benchmarks nach jedem Nightly-Build laufen lässt, und diese Seite zeigt sie ab der ersten Nacht, in der sie gelaufen sind.

In jedem Diagramm ist ein Balken die Zeit, die ein Programm gebraucht hat, im Verhältnis zu C auf derselben Eingabe. 1× ist so schnell wie C, und 2× hat doppelt so lange gebraucht. TorbScripts Binary ist der rote Balken.

Programm für Programm#

Zu jedem Programm steht hier, was es misst und wo TorbScript Arbeit macht, die das C nicht macht - denn dort fällt es zurück. Das C ist das schlichte Programm des Benchmarks Game mit einem Thread, nicht sein schnellstes, und das TorbScript folgt ihm Anweisung für Anweisung. Was sich hier zeigt, ist Arbeit für den Compiler: Nichts davon ist eine Eigenschaft der Sprache, und Performance hat die Einzelheiten.

binary-trees#

Baut Millionen kleiner Bäume, läuft sie ab und wirft sie weg: Speicher anfordern und freigeben. Ein Knoten in C ist ein malloc und ein free. Ein Knoten in TorbScript ist derselbe Block mit einem Referenzzähler darin, der beim Bauen und Ablaufen des Baums hoch- und heruntergezählt wird, und der Baum wird freigegeben, wenn ihn nichts mehr benutzt.

fannkuch-redux#

Dreht den Anfang kurzer Zahlenlisten um, wieder und wieder, für jede Reihenfolge der Zahlen: eine Liste über ihren Index lesen und schreiben. TorbScript prüft jeden Index gegen die Länge der Liste und jede Summe auf Überlauf; das C prüft beides nicht. Und jedes permutation[i] = value ist ein Aufruf in TorbScripts Laufzeit, in die der C-Compiler nicht hineinsieht, wo das C in ein Array schreibt.

n-body#

Bewegt fünf Planeten in kleinen Schritten: Rechnen mit Dezimalzahlen, auf den Feldern von Records, die in einer Liste liegen. Hier liegt TorbScript heute am weitesten zurück. Ein Planet sind sieben Zahlen, mehr als die 32 Bytes, die ein Record haben darf, um direkt in der Liste zu liegen; die Liste hält also einen Zeiger auf ihn - und bodies[i].velocityX = ... kopiert den ganzen Planeten, bevor es ein Feld davon ändert, wo das C das Feld über einen Zeiger ändert.

spectral-norm#

Multipliziert einen Vektor mit einer Matrix, deren Einträge unterwegs berechnet werden: eine Division und ein paar Multiplikationen pro Schritt, in zwei Schleifen über Listen von Dezimalzahlen. Wie bei fannkuch-redux ist jedes product[i] = ... ein Aufruf in die Laufzeit, und jeder Index wird geprüft.

mandelbrot#

Berechnet die Mandelbrot-Menge Punkt für Punkt und schreibt sie als Bitmap: Rechnen mit Dezimalzahlen in einer engen Schleife, und sonst nichts. Das ist das Programm, bei dem die beiden Sprachen dem C-Compiler den ähnlichsten Code geben.

fasta#

Schreibt DNA als Text, einen zufälligen Buchstaben nach dem anderen, sechzig pro Zeile. TorbScripts print gibt jede Zeile an das Betriebssystem, bevor es zurückkehrt; das C-Programm verlangt dasselbe mit setlinebuf, also machen beide einen Systemaufruf pro Zeile. Dazwischen sammelt TorbScript die Buchstaben einer Zeile in einer Liste und macht einen String daraus, wo das C jeden Buchstaben in den Puffer seiner Ausgabe legt.

Warum die VM langsamer ist#

torb run ist dafür da, ein Programm sofort zu starten, während du es schreibst. Seine VM ist jung und selbst in TorbScript geschrieben, und heute braucht sie ein Vielfaches der Zeit von Python. Am langsamsten ist sie, wo ein Programm in seiner innersten Schleife ein Feld eines Records in einer Liste oder ein Element einer Liste ändert - n-body und fannkuch-redux -, weil sie eine solche Stelle Schritt für Schritt über eine Beschreibung des Pfads erreicht. Der Entwurf der VM nennt, was als Nächstes kommt. Ihre Zeit auf dieser Seite enthält das Prüfen und Übersetzen des Programms, das die Zeile „Starten“ der Tabelle für sich misst.

Alle Zahlen#

Noch keine Zahlen: Die Tabelle füllt sich ab der ersten Nacht, in der die Benchmarks gelaufen sind.

Wie gemessen wird#

Was nicht gemessen wird#

Das sind kleine Programme, die je eine Sache tun, keine Anwendungen, und ein C-Compiler mit einem Satz Optionen. Nichts hier benutzt mehr als einen Kern. Was TorbScripts Abstraktionen kosten, Muster für Muster, und was noch nirgends gemessen wird, steht in Performance.

Selbst messen#

Jedes Programm und das Skript, das sie misst, liegen im Repository, in benchmarks/game/, mit der Lizenz der Programme, die aus dem Benchmarks Game stammen. In einem Checkout mit gebautem torb:

$ sh benchmarks/game.sh
$ sh benchmarks/game.sh --quick n-body

Das erste misst alles, wie die Forge, und schreibt benchmarks/out/game/benchmarks.json. Das zweite prüft nur, dass ein Programm in jeder Sprache baut, läuft und dasselbe ausgibt. Die Performance-Suite sagt mehr.

Esc