4 ms·
For a dynamic language to add static types solely to get performance seems like a hack to me. Make the dynamic language fast enough that you don't need static t
by headius 15y ago
For a dynamic language to add static types solely to get performance seems like a hack to me. Make the dynamic language fast enough that you don't need static types.
I can appreciate it was an explicit design decision. My calling it a "hack" is to blunt claims that Clojure is faster than equivalent JRuby code, when in actuality the Clojure code is not equivalent. Clojure doing fully boxed math performs similarly to JRuby doing fully boxed math. Apples to apples instead of apples to statically-typed oranges.
That said, I have wanted to do the same in JRuby. I do not have the freedom to make such a decision for Ruby, however, and Matz (Ruby's creator) has said there will never be static types. So...I will continue to work to make dynamic-typed math as fast as possible, and push the JVM to help me as much as it can. I won't hack around it :)
- cemerick 15y agoIt's a narrow point, but the coincidence of "make the dynamic language fast enough that you don't need static types" and talk about equivalent perf using boxed math reminds me of the old saw about a sufficiently smart compiler[1]. Yeah, maybe the hotspot/jrockit wizards will be able to wave a wand and make everything fast. But, until the stars align in that department,[2] being able (and in Clojure's case, defaulting) to fast, static, primitive math is a good thing IMO, and really, really important to getting work done in certain domains today. In the meantime, I greatly appreciate your pushing. :-D [1] http://c2.com/cgi/wiki?SufficientlySmartCompiler http://c2.com/cgi/wiki?SufficientlySmartCompiler [2] e.g. http://blogs.oracle.com/jrose/entry/fixnums_in_the_vm http://blogs.oracle.com/jrose/entry/fixnums_in_the_vm
- headius 15y agoI certainly agree. As an implementer of Ruby, I've wanted type-hinting escape hatches to make my job easier. Given that they're likely never going to happen, I will continue to optimize the hard way and work closely with JVM guys :)
- rbranson 15y agoJRuby generates direct, "static" dispatches to the Fixnum class when you throw the --fast flag. However, this is not backwards compatible with MRI Ruby, so it's not default. Clojure does not attempt to maintain compatibility with anything, so there you go.
- headius 15y agoThat's not true anymore. --fast is mostly eliminated now, with all features either on by default or replaced by better compilation. Math-like dispatches go through different dispatch logic optimized for Fixnums and Floats, this is true. If possible, they dispatch directly rather than dynamically. But they do this under global "isFixnumModified" and "isFloatModified" guards, to match Ruby behavior. The extra check did not significantly add to the overhead of math operations. Of course with invokedynamic, all dispatch is done the same way, and indy optimizes as well as our old tricks in both the unmodified and modified cases. Yay invokedynamic!
- rbranson 15y agoCool. Of course, the is-modified flags don't do much for large, idiomatic Ruby applications. As soon as anyone modifies Object, Class, or Fixnum (as seen in Rails), it goes right back to slow dispatch mode, which is why invokedynamic is so great.
- calibraxis 15y agoFor a dynamic language to add static types solely to get performance seems like a hack to me. Be that as it may, that's Common Lisp's approach as well. I never have added type annotations in Common Lisp, but I like the possibility of giving the compiler more info. (If I understand your point correctly.) The particularly nice thing is that you can get the disassembly of a function, to see what effects your changes have on optimization. (http://www.psg.com/~dlamkins/sl/chapter16.html http://www.psg.com/~dlamkins/sl/chapter16.html)
- headius 15y agoOf course you can get the disassembly of JITed code from Hotspot too, and the effects of boxed math are quickly visible. Escape analysis may help in the future, if it can be made more general. While I consider type hinting an uglyish wart to work around limitations of the underlying VM, I also secretly wish we had such an escape hatch in JRuby. Oh well.
- rbranson 15y agoType annotation wouldn't do much for Ruby honestly. Most idiomatic Ruby code (i.e. loading Rails into the object space at all) would break any optimization type annotation would yield. There's no compiler, so guards would have to be inserted to perform runtime type analysis (potentially very costly in Ruby). Common LISP actually has static, scalar types, so type annotation has direct application. Ruby doesn't really have a notion of types in the classical sense, and ALL dispatch targets (even those written in C or "primitives") are extensible and modifiable by Ruby code.
- headius 15y agoThis is one reason I never explored it. There has been some research into "gradually typing" dynamic-typed systems, and it gets hairy pretty quick. In any case, I know JRuby's not going to be able to get boxed math as fast as primitive math, and that's ok. We'll just make it easy to use languages that can do fast math, and make method invocation against normal objects as fast as possible to compensate.
- rbranson 15y agoI love your commitment to purity here. Things could certainly be made much faster in Ruby if most of what makes it useful in certain contexts were abandoned. The complexity of invocation alone seems to be fairly unique with the potentially vast tree of class/module hierarchy along with metaclass, method_missing, and first-class, dynamic invocation targets (classes and modules). I think many people don't realize that "Ruby is slow" because they're building on libraries that make extensive use of Ruby's dynamism with little regard given to performance. Imagine implementing Rails without *eval, method_missing and singleton classes. Pull up a Rails console in an application with a few plugins, run "included_modules" on a class, and you'll see how many potential modules are involved in invocation. The last Rails project I worked on has 61 modules included into ActiveRecord::Base, mostly by plugins. I think there is plenty of abuse of the extension facilities that results in this type of overhead (what justifies Ym4r::GmPlugin getting included into Class?), but this is the world in which we live.