Simple Virtual Machines
Terrence Parr presented an interesting introduction to virtual machines. He implemented a simple virtual machine, named appropriately. The code is available in a Java implementation and a C implementation on GitHub. I decided to implement it one of the worst languages you could imagine for such a task: Lua. Lua uses a virtual machine. So we'll have a virtual machine in a virtual machine. Lua doesn't even have an integer type or the
switch statement. This means the default word size is actually a double and the dispatch loop is fairly verbose. I tried a number of dispatch methods: an array of functions and a giant
if ... else. The array of opcodes is definitely more elegant in Lua but it was slower on my machine.
I created this implementation primarily to see the speed difference between Lua, Java, and C in an intense task. I forked the C version in order to switch to a computed goto. I expected this to offer a performance improvement.
# Calculate factorial(12) 1,000,000 times # simple virtual machine implementations luajit: 10.940s [13.7x] java: 3.114s [3.90x] c switch: 2.045s [2.56x] c goto: 0.798s [1.00x] # other virtual machines luajit 0.047s [0.06x] java 0.331s [0.41x] #warm up is long lua 1.591s [1.99x] ruby 2.569s [3.22x] python 4.175s [5.23x]
Performance is as expected. LuaJIT, which seems to compile every opcode, was not as fast as Java. But being a dynamic language, 3.5x slower isn't too bad. Java seems to have a really good JIT compiler. In this case it is only 50% slower than the equivalent C. C only gets much faster when you use ugly optimizations. The computed goto is ugly and non-portable but, as expected, fast. The code for the other languages is on gist.