Running Lua in a browser via Emscripten
mozakai.blogspot.com
mozakai.blogspot.com
With asm.js in Firefox nightly it's nearly native speed.
For reference, I'm using 2012 MBA with Firefox 23.0a2 (2013-05-30) (clean profile, just to be sure) and Chrome 27.0.1453.93.
This finding demonstrates that asm.js isn't significantly less efficient than LLVM bitcode or native code, even though it's text.
Tell that to someone on a mobile device with poor connectivity.
> In particular, remember that the Lua VM is often significantly faster than other dynamic languages like Python and Ruby. These languages are useful in many cases even if they are not super-fast.
Something people often overlook is that performance is highly dependent on where the code runs. Ruby is fine for server-side programs because you can always go fast by throwing more hardware at it.
Languages that run on end-user machines don't have that luxury. This is why the playing field for client-side programming languages is much more constrained and why C++ is still hugely popular there. It's also why so much work has gone into optimizing JavaScript.
Being half as fast as JS could be tolerable for some apps, but that means your app will likely be slow and stuttery in some cases. When it is, there's little you can do about it. Is Lua that much of an improvement over JS to justify that?
> There are however some tricky issues, for example we can't do cross-VM cycle collection - if a Lua object and a JavaScript object are both not referred to by anything, but do refer to each other, then to be able to free them we would need to be able to traverse the entire heap on both sides, and basically do our own garbage collection in place of the browser's - for normal JavaScript objects, not just a new type of objects like Lua ones.
This is a huge deal. It basically means if you use this, your app is very likely to leak memory unless you are very careful. The difficulty of being appropriately careful is exactly why we moved to GC languages in the first place.
WebKit (now Blink on the Google side) actually has a similar problem already: WebKit manages memory for the DOM separately from V8's garbage collector. This adds a bunch of complexity to the browser to deal with those cycles and has, I think, a significant performance cost.
It's enough of an issue that the Chrome team is starting a new project ("oilpan") to provide a unified GC shared by both V8 and the DOM.
Don't get me wrong, I think this is a very cool hack. But I don't think it says much about the viability for using something like this for real apps, at least not yet.
This depends on the project, of course. For existing software that's already written in Lua and now needs to run inside a browser, running the Lua VM in JS may be the best way to go. However, I've decided that for new code, Lua doesn't have enough advantages over JS to justify the problems with running a VM in a VM.
Here are the things that I consider significant advantages of Lua over JS, and my thoughts on each.
1. Coroutines: JS is getting a form of these via generators, though I don't know how soon that feature will become ubiquitous. In the meantime, a compiler can turn code that uses coroutines into continuation-passing style.
2. Weak references: It's unfortunate that JS doesn't have these. But as the OP pointed out, running a VM within a VM introduces other memory management problems, since the guest VM has its own GC. To avoid those issues, I can live without weak references in the language.
3. Metamethods: The most well-known metamethods are for overriding table operations, so one can implement properties, proxies, or other dynamic behavior. I've sometimes found these useful on previous Lua projects, but for new code, I can do without them in order to avoid the problems of running a VM in a VM.
4. Non-string keys for tables/objects: There are ways around this. For example, instead of using another object as a key, one can assign a unique ID to the object, then use that as the key.
There has been some discussion about adding more powerful weak refs to JavaScript, but I'm not sure where that discussion stands.
(For what I'm doing that's outweighed by the convenience of direct browser support, but to me that's the big attraction.)
If the choice is lua.js vs porting code to Dart you know 'good enough' is going to win.
Please just embed the damn thing in a browser already. It's been way too long without any competiton to Javascript being allowed.
But the way things are standing now it's not gonna happen. JavaScript, for the better and worse, is what we are stuck with. No browser vendor will be able to push though another language, and no standards committee would suggest a second scripting language to the web that runs alongside JavaScript.
If you absolutely cannot stand programming in JavaScript, which is the only native option for the web, you have to make do with the "language written on top of another language" solutions that are so popular these days, along with it's somewhat costy overhead.
Note however that Google has not actually shipped NaCl or Dart. (NaCl technically ships in Chrome, but is disabled on the web by default, it is only usable in the Chrome Store.) So currently no browser is shipping a new nonstandard VM - which is good, because if a major browser did that it could fragment the web.
I guess it is caused by the storage limitations. We can't rely on the mobile browser cache, at least for now.
What we need is a similarly narrow target JS subset for dynamic languages where the outer GC is actually functional and lookup/inline cache kinds of optimizations can be performed on correctly generated code.
So even if we duplicate by compiling another GC, we are enabling new types of GCing, it isn't an exact clone.
This is reinventing the wheel so that you have the ability to ensure the wheels you are using are actually round.
While there are potential performance benefits in using a provided-system, something like Garbage Collection is a pillar upon which most of the program rests. I wouldn't trust the behaviour of all of the existing implementations to seamlessly work the same way reliably. If you discover a flaw in the system, being able to fix it can allow you to continue working. That is much better than filing a bug-report and waiting for the development cycle to churn out a released fix.
In this case, the Lua code could be even faster than the equivalent JS code on some applications where LuaJIT generates better code than V8/IonMonkey (even considering the 2x slowdown of asm.js wrt native).
The relevant yo dawg joke would be "I heard you like JITs so we put LuaJIT on your OdinMonkey so you can JIT while you JIT"
[1]: http://kripken.github.io/lua.vm.js/lua.vm.js.html
Therefore V8 is not the ideal platform for benchmarking this implementation. You could try with a nightly Firefox.
EDIT: Indeed, 8 MFLOPS on FF Aurora, 1.2 MFLOPS in Chrome Canary.
I wonder how difficult it would be to convert Lua to C++ with exceptions.