In the open source Smalltalk community we have a pretty fast VM these days - its called Cog and is written by the highly gifted and experienced Eliot Miranda who also happens to be a really nice guy! Cog is fast and its also still improving with some more developers joining recently.
Lies and, well basically just lies…
In Squeak Smalltalk we have this silly little benchmark called tinyBenchmarks. It’s not for benchmarking. No, let me repeat that - it really is not.
But hey, let’s just ignore that for a second. :) And oh, comparing Lua vs Smalltalk - speed is only a tiny piece of the picture - there are other much more interesting characteristics of these two eco systems that would affect any kind of “choice”:
- Smalltalk implementations typically have live reflective rich IDEs, and excel at complex domain models and interactive explorative development. And very clean late bound OO. Not so good at “playing well with others” though.
- Lua, and especially LuaJIT, is extremely good at playing with others - and specifically the C/C++ eco system. As a more traditional scripting language you have more choices in IDEs and SCM tools etc, but it is not as interactive and exploring as Smalltalk and is not focused at OO specifically, although it can do it pretty good. It does however have several good IDEs, but hardly anything matching a Smalltalk IDE.
So Smalltalk excels in interactive development - but you are often limited in integration options… while Lua excels as a dynamic language thriving as a catalyst in the C and C++ eco system.
These languages and their tools were simply born from two very different sets of goals. And Lua is also different from say Python, since Lua in contrast was designed as a minimal language (in many ways like Smalltalk was) and a language meant for embedding in a C/C++ application (almost no batteries included). This carves out a fairly unique niche for Lua.
Ok, so back to tinyBenchmarks. It consists of two small snippets of code, one measures “bytecode speed” by counting primes in a few nested loops and another is a recursive function similar to Fibonacci that just counts the number of recursive calls. Ok, so… latest Cog (binary VM.r3000) vs latest LuaJIT2 (2.1.0-alpha), here follows the Lua code I whipped up. I tried basically three different variants on the Fibonacci recursion to see how much penalty an OO design would give.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
And the Smalltalk code would be:
I picked 100000 and 47 to get fairly long running times, so LuaJIT:
10.248302 bytecode secs 26.765077 benchFib send secs (normal Lua) 70.418739 Bench send secs (OO Lua) 71.003568 Benchy send secs (OO Lua Classy)
49.606 bytecode secs 58.224 send secs
So LuaJIT2 is about 4x faster on bytecode speed and 2x faster on recursive calls.
But wait, lots of things to note here:
- These are two trivial benchmarks meant to detect really bad regressions in VM code, not benchmarking.
- The above. Read it again.
- A recursive function call in Lua is not the same thing as a message send with full OO lookup in Cog. If we look at Bench and Benchy we see that 2x factor vanish!
- Integer math is clearly different in Lua vs Smalltalk. Lua does doubles only, Smalltalk has a full math system falling back to “big ints” when needed!
- Using Classy was the same speed as manual metatable approach. So in Lua you would definitely use such a lib instead of manual OO, much easier and with nice features.
- And oh, both grabbed a single core by the throat doing this - Cog even managed to squeeze out 104%! :)
There is no real conclusion from the silly benchmark - it was just a fun exercise! I already knew Cog is pretty darn fast and LuaJIT is the King of the Hill - it even beats V8 regularly. Cog on the other hand is executing a much more refined and advanced language and object system, you really do need to keep that in mind here.
Python could never keep me interested, although I did try - but it kept turning me off, so unclean, lots of different mechanisms, too complicated. Same story with Ruby, too messy, no elegance and a community drug crazed with nifty tricks… IMHO.
But Lua has that smallness that Smalltalk has, it feels “designed”. It has strong abstractions that it carries through all the way. In short it doesn’t turn me off. And then, a lot more in this eco system is pure candy. LuaJIT2 has awesome speed. Very powerful interoperability with C and C++, in fact, the LuaJIT FFI can call C libraries as fast as C can! Tons of good libraries and tools. Very strong on mobile development. Many interesting projects like TurboLua, Tarantool, OpenResty, Lapis, Metalua etc etc.
Always nice to realize that there still is stuff out there that can attract an old Smalltalk dog… :)