I talked a bit with John Rose about this, and he agreed with me that a good partial measure might be to add APIs for getting a *partial* stack.
Currently, Hotspot will limit how deep a stack trace it generates. This can have a very large impact on the performance of generating traces. The magic flag is -XX:MaxJavaStackTraceDepth=####, and the default on my system is 1024. Here's a set of benchmarks of various trace depths from 1000 down to 2. Once you get down to 100 frames, performance of generating a stack trace starts to improve considerably. https://gist.github.com/headius/5365217 Unfortunately there's no API to get just a partial stack trace, via JVMTI or otherwise. The relevant code in Hotspot itself is rather simple; I started prototyping a JNI call that would allow getting a partial trace. Perhaps something like: thread.getStackTrace(depth) ...and something equivalent for JVMTI. John agreed that this would be a worthwhile feature for a JEP, and I'd certainly like to see it trickle into a standard API too. - Charlie On Thu, Apr 11, 2013 at 3:37 AM, <william.lo...@jinspired.com> wrote: > Hi Bob, > > I wrote an article last year on the cost and impact of JVMTI stack collection. > > http://www.jinspired.com/site/is-jvm-call-stack-sampling-suitable-for-monitoring-low-latency-trading-apps > > I would prefer to see the JVM come up with a standard API and mechanism to > allow the stack to be augmented with additional frames that not only include > Java code but more contextual information related to executing activity > (code, block, flow,....) this would include other JVM languages. > > We provide this sort of thing already today for Java, JRuby/Ruby and > Jython/Python, even SQL, in our metering engine but would welcome an ability > to replicate this data to the VM itself so standard tools need not be > changed. What is cool about this is that we can simulate a stack in a remote > JVM that spans multiple real application runtimes. > > http://www.jinspired.com/site/jxinsight-opencore-6-4-ea-12-released > > Kind regards, > > William > >>-----Original Message----- >>From: Bob Foster [mailto:bobfos...@gmail.com] >>Sent: Sunday, July 8, 2012 01:32 AM >>To: jvm-langua...@googlegroups.com >>Cc: 'Da Vinci Machine Project' >>Subject: Re: [jvm-l] Improving the performance of stacktrace generation >> >>> Any thoughts on this? Does anyone else have need for >>lighter-weight name/file/line inspection of the call stack? >> >>Well, yes. Profilers do. >> >>Recall Cliff Click bragging a couple of years ago at the JVM Language >>Summit about how fast stack trace generation is in Azul Systems' OSs...and >>knocking Hotspot for being so slow. It turns out that stack trace >>generation is a very significant overhead in profiling Hotspot using JVMTI. >>Even CPU sampling on 20 ms. intervals can add 3% or more to execution time, >>almost entirely due to the delay in reaching a safe point (which also >>guarantees the profile will be incorrect) and generating a stack trace for >>each thread. >> >>But 3% is peanuts compared to the cost of memory profiling, which can >>require a stack trace on every new instance creation. In a profiler I wrote >>using JVMTI, I discovered that it was faster to call into JNI code on every >>method entry and exit (and exception catch), keeping a stack trace >>dynamically than to call into JNI only when memory was allocated and >>request a stack trace each time. The "fast" technique is about 3-10 times >>slower than running without profiling. The Netbeans profiler doesn't use >>this optimization, and its memory profiler when capturing every allocation, >>as I did, is 2-3 ORDERS OF MAGNITUDE slower than normal (non-server) >>execution. >> >>Faster stack traces would benefit the entire Hotspot profiling community. >> >>Bob >> >>On Sat, Jul 7, 2012 at 3:03 PM, Charles Oliver Nutter >><head...@headius.com>wrote: >> >>> Today I have a new conundrum for you all: I need stack trace >>> generation on Hotspot to be considerably faster than it is now. >>> >>> In order to simulate many Ruby features, JRuby (over)uses Java stack >>> traces. We recently (JRuby 1.6, about a year ago) moved to using the >>> Java stack trace as the source of our Ruby backtrace information, >>> mining out compiled frames and using interpreter markers to peel off >>> interpreter frames. The result is that a Ruby trace with mixed >>> compiled and interpreted code like this >>> (https://gist.github.com/3068210) turns into this >>> (https://gist.github.com/3068213). I consider this a great deal better >>> than the plain Java trace, and I know other language implementers have >>> lamented the verbosity of stack traces coming out of their languages. >>> >>> The unfortunate thing is that stack trace generation is very expensive >>> in the JVM, and in order to generate normal exceptions and emulate >>> other features we sometimes generate a lot of them. I think there's >>> value in exploring how we can make stack trace generation cheaper at >>> the JVM level. >>> >>> Here's a few cases in Ruby where we need to use Java stack traces to >>> provide the same features: >>> >>> * Exceptions as non-exceptional or moderately-exceptional method results >>> >>> In this case I'm specifically thinking about Ruby's tendency to >>> propagate errno values as exceptions; EAGAIN/EWOULDBLOCK for example >>> are thrown from nonblocking IO methods when there's no data available. >>> >>> You will probably say "that's a horrible use for exceptions" and I >>> agree. But there are a couple reasons why it's nicer too: >>> - using return value sigils requires you to propagate them back out >>> through many levels of calls >>> - exception-handling is cleaner in code than having all your errno >>> handling logic spliced into regular program flow >>> >>> In any case, the cost of generating a stack trace for potentially >>> every non-blocking IO call is obviously too high. In JRuby, we default >>> to having EAGAIN/EWOULDBLOCK exceptions not generate a stack trace, >>> and you must pass a flag for them to do so. The justification is that >>> these exceptions are almost always used to branch back to the top of a >>> nonblocking IO loop, so the backtrace is useless. >>> >>> * Getting the current or previous method's name/file/line >>> >>> Ruby supports a number of features that allow you to get basic >>> information about the method currently being executed or the method >>> that called it. The most general of these features is the "caller" >>> method, which provides an array of all method name + file + line that >>> would appear in a stack trace at this point. This feature is often >>> abused to get only the current or previous frame, and so in Ruby 1.9 >>> they added __method__ to get the currently-executing method's >>> name+file+line. >>> >>> In both cases, we must generate a full Java trace for these methods >>> because the name of a method body is not necessarily statically known. >>> We often want only the current frame or the current and previous >>> frames, but we pay the cost of generating an entire Java stack trace >>> to get them. >>> >>> * Warnings that actually report the line of code that triggered them >>> >>> In Ruby, it is possible to generate non-fatal warnings to stderr. In >>> many cases, these warnings automatically include the file and line at >>> which the triggering code lives. Because the warning logic is >>> downstream from the Ruby code, we again must use a full Java stack >>> trace to find the most recent (on stack) Ruby frame. This causes >>> warnings to be as expensive as regular exceptions. >>> >>> Because the use of frame introspection (in this case through stack >>> traces) has largely been ignored on current JVMs, I suspect there's a >>> lot of improvement possible. At a minimum, the ability to only grab >>> the top N frames from the stack trace could be a great improvement >>> (Hotspot even has flags to restrict how large a trace it will >>> generate, presumably to avoid the cost of accounting for deep stacks >>> and generating traces from them). >>> >>> Any thoughts on this? Does anyone else have need for lighter-weight >>> name/file/line inspection of the call stack? >>> >>> - Charlie >>> >>> -- >>> You received this message because you are subscribed to the Google Groups >>> "JVM Languages" group. >>> To post to this group, send email to jvm-langua...@googlegroups.com. >>> To unsubscribe from this group, send email to >>> jvm-languages+unsubscr...@googlegroups.com. >>> For more options, visit this group at >>> http://groups.google.com/group/jvm-languages?hl=en. >>> >>> >> > > > _______________________________________________ > mlvm-dev mailing list > mlvm-dev@openjdk.java.net > http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev _______________________________________________ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev