5 ms·
it makes me wonder why languages like ruby are so slow.
by toisanji 17y ago
it makes me wonder why languages like ruby are so slow.
- mbrubeck 17y agoRuby might just need a better implementation with more time spent on optimization. http://maglev.gemstone.com/ http://maglev.gemstone.com/ is going in this direction. But also, Lua was always designed with cleanness and simplicity of implementation in mind. Its developers have strong backgrounds in both theory and engineering, which you can see in their interview in the book Masterminds of Programming. They've been very conservative about the design of the language. In contrast, Ruby feels much messier and more "evolved" - look at its Yacc grammar[1], for example, compared to the grammar of JavaScript or Lua[2]. Even the Ruby lexer is full of weird edge cases. Much of MRI is like that, and for years it was the only "spec" for the language; now its decisions have been reverse-engineered and inherited by all other implementations. [1]: http://blog.nicksieger.com/articles/2006/10/27/visualization-of-rubys-grammar http://blog.nicksieger.com/articles/2006/10/27/visualization... [2]: http://www.lua.org/manual/5.1/manual.html#8 http://www.lua.org/manual/5.1/manual.html#8 [By the way, I've used Ruby for years and like it at lot, while I've written only a few lines of Lua code and like it but am not deeply familiar with it.]
- dchest 17y agoAlso, "The Evolution of Lua" — an interesting paper that shows how they came to this fast and somewhat elegant language: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.72.3859&rep=rep1&type=pdf http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.72.... [PDF]
- silentbicycle 17y agoAlso good: "The Implementation of Lua 5.0" (http://www.tecgraf.puc-rio.br/~lhf/ftp/doc/sblp2005.pdf http://www.tecgraf.puc-rio.br/~lhf/ftp/doc/sblp2005.pdf). Past discussion: http://news.ycombinator.com/item?id=617278 http://news.ycombinator.com/item?id=617278 If you want to learn Lua, Ierusalimschy's _Programming in Lua_ (http://www.inf.puc-rio.br/~roberto/pil2/ http://www.inf.puc-rio.br/~roberto/pil2/) is by far the best book. Lua is one of my favorite languages. While it's good on its own, you'll get a lot more out of it if you're comfortable with C. Lua+C is an excellent combination.
- ambulatorybird 17y agoJust chiming in as another Lua fan; I really like it because it's like the Scheme of imperative scripting languages. And while we're passing around links to papers, I've found the following the be good for additional insight: Lua Performance Tips: (http://www.lua.org/gems/sample.pdf http://www.lua.org/gems/sample.pdf) A No-Frills Introduction to Lua 5.1 VM Instructions: (http://luaforge.net/docman/view.php/83/98/ANoFrillsIntroToLua51VMInstructions.pdf http://luaforge.net/docman/view.php/83/98/ANoFrillsIntroToLu...)
- yread 17y agoAgree. If you want to learn more about Lua+C check out sources of this awesome game: http://springrts.com/ http://springrts.com/
- derefr 17y agoIt'd be interesting to see how fast Ruby would run "cached" (i.e. with the AST already assembled in memory,) to see how much of the time is really spent in the parsing and lexing phases.
- mbrubeck 17y agoNote that I'm not claiming Ruby's parser and lexer are slow, or that they're the cause of any greater problems. I'm just picking on them as one example of deeper differences between the Ruby and Lua designs/implementations.
- haberman 17y agoAlso, Ruby has much more complicated rules for method dispatch. Lua just has functions, and if you want to implement any more complicated dispatch, you have to do it yourself. Once I implemented Ruby-like dispatch on top of Lua, and it was terribly slow: http://blog.reverberate.org/2009/02/09/disappointment/ http://blog.reverberate.org/2009/02/09/disappointment/ To make a long story short, porting my existing Lua project to use my Ruby-like method dispatch resulted in a 4x slowdown.
- stcredzero 17y agoRuby might just need a better implementation with more time spent on optimization...But also, Lua was always designed with cleanness and simplicity of implementation in mind Ease of implementation has a multiplier effect with Open development effort. Not only do you get more of "more eyeballs," new contributors can ramp up faster. There tends to be a better effort/ fun ratio. Even the Ruby lexer is full of weird edge cases. Actually, the lexer sets state that changes the operation of the parser and vice versa.
- mikemike 17y agoSome of Ruby's more excentric semantics are really hard to optimize away by a compiler. It takes a much greater effort to compile Ruby source code to machine code of similar quality than for Lua. Since time and money are not infinite resources, especially for compiler development, you'll get worse results in practice. So, yes, language design does impact performance.
- haberman 17y ago> Some of Ruby's more excentric semantics are really hard to optimize away by a compiler. Any examples in particular? Besides name resolution and method dispatch (and callcc, but I think that may have even been removed from Ruby 1.9) none of Ruby's semantics seem all that different from Lua. Am I missing something? I guess there's also throw/catch and exceptions.
- mikemike 17y agoMostly resolution and dispatch. Some of this needs very clever caching or the overhead can't be eliminated or hoisted. The control-flow constructs and iterators come to mind, too. The Rubyists certainly know about these issues, so you'll have to ask them for details.
- blasdel 17y agoThere's also the over-featured thread implementation (especially before 1.9) Dispatch is worse than you realize due to the hackish optimizations made in MRI: if you monkeypatch a natively-method from Ruby, other native code will call the original by default.
- WalkingDead 17y agoHere is a step by step comparison on how cutting off ruby's features can make the JRuby implementation faster, from the guy who worked on JRuby. http://blog.headius.com/2009/04/how-jruby-makes-ruby-fast.html http://blog.headius.com/2009/04/how-jruby-makes-ruby-fast.ht... Read it, you will find it interesting. The guy also wrote a small language called Duby which used Ruby like syntax but is much more faster, because he didn't include any of those slowing down features.
- blasdel 17y agoRuby was just designed and implemented with all the attention paid to sugary syntax/semantics and very little thought given to how well it could be implemented. MRI is a really poor implementation of a (formerly) poorly-specified, highly irregular, unorthogonal language. MRI's garbage collector is abysmal, use Phusion's REE fork to get one that at least doesn't mark every single object on every collection and actually bothers to perform them in normal situations. It didn't do any desugaring at all until 1.9, and YARV only has bytecodes for the most primitive accessors, assignments, stackops, jump/condjump, and returns; with optimizations for -, +, <. <<, and some regexes. Your normal code just gets passed through verbatim. Every once in a while I'll be reading docs or sitting in irb and suddenly scream at the ceiling, spin in my chair, and get the urge to throttle a Japanese person.
- sjs 17y agoNo need to wonder, have a look at the source code for them both and it will become clear exactly why there is such a performance difference. Lua gives you raw C numeric types which makes a big difference right there. Other people have mentioned a few other good reasons too (no costly method dispatch). I haven't looked at LuaJIT yet but considering how small it is I'm sure it meets or exceeds the quality of the code behind Lua.
- chancho 17y ago> Lua gives you raw C numeric types Standard Lua (the one from PUC-Rio) doesn't really, it uses boxed numeric values, as I imagine ruby (and almost every other dynamic language) does as well. "Boxed" meaning that each number is stored on the heap with some kind of tag, and when you pass such a value to a function you're really passing a pointer to it and that indirection costs cycles and puts pressure on the cache. LuaJIT's most significant (IMO) feature is that it stores numeric values directly, like C does, so when you call a function the actual bits representing it go right on the stack, not the address of where the bits can be found, and it uses some cool tricks of floating point representation to prevent the garbage collector from trying to follow these stack values as if they were pointers. This (combined with the trace optimization) is why when you write a numeric for-loop in LuaJIT it runs (nearly?) as fast a C.
- mascarenhas 17y agoLua numbers are not boxed in the usual sense; they live in the Lua data stack (which leaves in the C heap, but this is not isomorphic to the Lua heap), are not accessed through a pointer, and do not put pressure on Lua's memory allocator and garbage collector. LuaJIT 2's NaN tagging alone does not speed up the stock interpreter: http://article.gmane.org/gmane.comp.lang.lua.general/44823 http://article.gmane.org/gmane.comp.lang.lua.general/44823.
- deleted 17y ago[deleted]
- cpr 17y agohttp://www.macruby.org/ http://www.macruby.org/ -- Apple's supporting an OSS project to use LLVM for real compilation, getting Ruby within spitting distance of Objective-C. Of course, the fact that it's tied to the Objective-C runtime means it's not portable as-is, but at least it's a proof that Ruby need not be slow.