How fast is TorbScript?

Six well-known programs, each in TorbScript, C, Python and JavaScript, measured every night on the same machine - a TorbScript program built with torb build against C, and torb run against Python and Node.js.

TorbScript runs a program in two ways. torb build turns it into a program file of its own, through C and a C compiler. torb run starts it at once, in the VM - an interpreter inside torb that needs no compiler.

This page measures both. The programs are six from the Computer Language Benchmarks Game, the collection people use to compare languages, and each runs against the same program in C, Python and JavaScript.

Nothing is measured yet. The numbers come from the forge's Linux runner, which runs the benchmarks after every nightly build, and this page shows them from the first night they ran.

In every chart, a bar is the time a program took, relative to C on the same input. 1× is as fast as C, and 2× took twice as long. TorbScript's binary is the red bar.

Program by program#

Each program says what it measures, and where TorbScript does work that the C does not - which is where it falls behind. The C is the plain, single-threaded program of the Benchmarks Game, not its fastest one, and the TorbScript follows it statement for statement. What is found here is work for the compiler: none of it is a property of the language, and Performance has the details.

binary-trees#

Builds millions of small trees, walks them and throws them away: allocating and freeing memory. A C node is a malloc and a free. A TorbScript node is the same block with a reference count in it, which is raised and lowered as the tree is built and walked, and the tree is freed when nothing uses it any more.

fannkuch-redux#

Reverses the front of short lists of numbers, again and again, for every order of the numbers: reading and writing a list by its index. TorbScript checks every index against the length of the list, and every sum for overflow; the C checks neither. And every permutation[i] = value is a call into TorbScript's runtime, which the C compiler cannot see into, where the C stores into an array.

n-body#

Moves five planets in small steps: arithmetic with decimal numbers, on the fields of records that live in a list. This is where TorbScript is furthest behind today. A planet is seven numbers, more than the 32 bytes a record may have to be stored inside the list, so the list holds a pointer to it - and bodies[i].velocityX = ... copies the whole planet before it changes one field of it, where the C changes the field through a pointer.

spectral-norm#

Multiplies a vector by a matrix whose entries are computed on the fly: one division and a few multiplications per step, in two loops over lists of decimal numbers. As in fannkuch-redux, every product[i] = ... is a call into the runtime, and every index is checked.

mandelbrot#

Computes the Mandelbrot set point by point and writes it as a bitmap: arithmetic with decimal numbers in a tight loop, and nothing else. It is the program where the two languages hand the C compiler the most similar code.

fasta#

Writes DNA as text, one random letter at a time, sixty to a line. TorbScript's print hands every line to the operating system before it returns; the C program asks for the same with setlinebuf, so both make one system call per line. In between, TorbScript collects a line's letters in a list and makes one String of them, where the C puts each letter into the buffer of its output.

Why the VM is slower#

torb run is for starting a program at once while you write it. Its VM is young and written in TorbScript itself, and today it takes several times as long as Python. It is slowest where a program changes a field of a record in a list, or an element of a list, in its innermost loop - n-body and fannkuch-redux - because it reaches such a place step by step through a description of the path. The design of the VM lists what comes next. Its time on this page includes checking and compiling the program, which the "starting up" row of the table measures on its own.

All the numbers#

No numbers yet: the table fills from the first night the benchmarks ran.

How it is measured#

What is not measured#

These are small programs that do one thing each, not applications, and one C compiler with one set of flags. Nothing here uses more than one core. How much work TorbScript's abstractions cost, pattern by pattern, and what is not measured anywhere yet, is in Performance.

Measure it yourself#

Every program and the script that measures them are in the repository, in benchmarks/game/, with the licence of the programs that come from the Benchmarks Game. From a checkout with a built torb:

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

The first measures everything, as the forge does, and writes benchmarks/out/game/benchmarks.json. The second only checks that one program builds, runs and agrees in every language. The performance suite says more.

Esc