Rocky Bernstein wrote: > Currently we do not optimize away call frame information in most cases, > > > Most cases? You wrote before ... > > which gave me the impression that "optimizing frames away" was important > for JRuby. > We statically, conservatively optimize away frames at present. - Ruby-based methods always have frame objects right now - Java-based core class methods have frames if they need to have frames, such as if they call back out to Ruby again or need to show up in a backtrace. But in many cases, we do not bother allocating a frame for most core methods. This has the benefit of improving performance substantially, but sometimes alters stack traces. I've been looking into a few areas to minimize the cost of frames: 1) a more aggressive static optimization to omit frames when they're not needed. Performance improves quite a bit as a result: Framed method dispatch benchmark Test ruby method: 100k loops calling self's foo 100 times 1.241000 0.000000 1.241000 ( 1.157000) 0.970000 0.000000 0.970000 ( 0.970000) 0.830000 0.000000 0.830000 ( 0.830000) 0.826000 0.000000 0.826000 ( 0.827000) ... Unframed: Test ruby method: 100k loops calling self's foo 100 times 1.214000 0.000000 1.214000 ( 1.130000) 0.351000 0.000000 0.351000 ( 0.351000) 0.331000 0.000000 0.331000 ( 0.331000) 0.259000 0.000000 0.259000 ( 0.259000) 0.249000 0.000000 0.249000 ( 0.249000) 0.246000 0.000000 0.246000 ( 0.246000) ... For comparison, Ruby 1.9: Test ruby method: 100k loops calling self's foo 100 times 0.920000 0.010000 0.930000 ( 0.928233) 0.930000 0.000000 0.930000 ( 0.929611) 0.920000 0.000000 0.920000 ( 0.925376) 0.920000 0.000000 0.920000 ( 0.926120) 0.920000 0.010000 0.930000 ( 0.925559) But this isn't enabled by default in JRuby because it destroys exception backtraces (since there's no frames, there's no way to report each call in the backtrace)...so then.... 2) Using the Java backtrace for Ruby's backtrace. This would allow JRuby to piggyback on all the optimization Java does for frames and backtraces, but allow me to eliminate my heap-based frame objects when I know they won't be used. Then heap-based frame objects would only be necessary for call state that must cross call boundaries. Really the primary limiting factor for JRuby to omit frame objects is being able to supply a useful backtrace. Why can't we just use Java's backtrace all the time? JRuby supports both interpreted and compiled execution...so Java's backtrace may show a mix of compiled and interpreted logic. > Nevertheless, unless this is the case that it can /never/ happen when > caller() is used, what in fact happens now? We would probably flag 'caller' as a "special" method since it can access information beyond the reach of the calling method, and using it would deoptimize. But of course it complicates other things...use of caller could happen after calls higher in the stack have been optimized to run without framing...in which case caller will not be able to get accurate information. > Personally, I don't see anything wrong clarifying the explanation of > caller() to mean that it gives reports the frames it sees is currently > there if that's in fact what's going on in the YARV and JRuby > implementations. The other alternative of course is to have these > implementations try to support caller as though no frames were removed. Is it useful if the result could vary depending on how you write your code and how long the code has run? Another option is that various features like this that require extra performance-degrading bookkeeping would be enabled or disabled by a flag, as in JRuby's ObjectSpace implementation (where each_object only worked for Class by default, but +O makes it work for everything). That would allow folks interested in using the feature to enable it (or leave it enabled) and those interested in more performance but fewer features to turn it off. This is the approach we're taking with many features in Ruby; you can choose to use them or not use them, and the performance implications are in your hands. - Charlie - Charlie