Draft JEP: Efficient Stack Walking API (original) (raw)
Remi Forax forax at univ-mlv.fr
Wed Jul 9 14:11:30 UTC 2014
- Previous message: Draft JEP: Efficient Stack Walking API
- Next message: RFR [8035975] Pattern.compile(String, int) fails to throw IllegalArgumentException
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On 07/09/2014 03:42 PM, David M. Lloyd wrote:
Just want to say that I am also looking forward to progress on this.
so am i :)
Rémi
On 07/09/2014 12:25 AM, Jeremy Manson wrote: Thanks for the response, Mandy. I'm looking forward to seeing the final version.
For CallerFinder, we use reflective goop to get at sun.misc.JavaLangAccess.getStackTraceElement. It requires us to build a Throwable (with associated stacktrace), but not to generate all of those StackTraceElement[] strings. This saves a lot of CPU cycles over something like Thread.getStackTrace(), but in this case, cheaper is better, and we'd definitely prefer a better solution. Functions like JavajavalangThrowablefillInStackTrace are still big cycle consumers. Jeremy
On Mon, Jul 7, 2014 at 8:06 PM, Mandy Chung <mandy.chung at oracle.com> wrote: Hi Jeremy, Thanks for the feedback and the CallerFinder API you have.
On 7/7/2014 9:55 AM, Jeremy Manson wrote: Hey folks, I don't know if Mandy's draft JEP has gotten any love, The JEP process is in transition to 2.0 version. Hope this JEP will come out soon. but this is something that has (in the past) been a major CPU cycle consumer for us, and we've had to invent / reinvent many wheels to fix it internally, so we'd love to see a principled solution. A couple of notes: - A large percentage of the time, you just want to find one of: 1) The direct caller of the method, 2) The first caller outside a given package. The current thinking is to allow you to find the direct caller as well as express the predicate for filtering that will cover these cases. We added a CallerFinder API that basically looks like this: // Finds the caller of the invoking method in the current stack that isn't in one of the excluded classes public static StackTraceElement findCaller(Class<?>... excludedClasses); // Finds the first caller of a given class public static StackTraceElement findCallerOf(Class<?>... classesToFind); This isn't the ideal API (it is more the one that happened to be convenient when we threw together the class), but it gets the vast majority of use cases. Does it use Thread.getStackTrace() to implement this CallerFinder API? Thread.getStackTrace or Throwable.getStackTrace both eagerly capture the entire stack trace that is expensive. We want to have the VM to be able to only capture the stack frames that the client needs and the implementation as efficient as possible. 2) Even with a super-efficient stack walker, anyone who uses the java.util.logging framework pervasively is going to see a lot of CPU cycles consumed by determining the caller. The current LogRecord implementation calls new Throwable that has to pay the cost of capturing the entire stack. We've had a lot of luck minimizing this by using a bytecode rewriter to change callers of log(msg) to log(sourceClass, sourceMethod, msg). This is almost certainly something that could be done (even in a principled way!) by the VM; improvements to CPU usage in such apps have been dramatic. Thanks. I'll make sure to measure and compare the performance with java.util.logging using the new stack walk API and also may ask your help to determine if you observe the performance difference comparing the rewritten bytecode vs the java.util.logging using the new API. Mandy Jeremy
On Sun, Mar 30, 2014 at 4:02 PM, Mandy Chung <mandy.chung at oracle.com> wrote: Below is a draft JEP we are considering submitting for JDK 9. Mandy ---------------------------- Title: Efficient API for Stack Walking Goal ---- Define a standard API for stack walking that will be efficient and performant. Non-goal -------- It is not a goal for this API be easy to use via Reflection for example use in code that is compiled for an older JDK. Motivation ---------- There is no standard API to obtain information about the caller's class and traverse the execution stack in a performant way. Existing libraries and frameworks such as Log4j and Groovy have to resort to using the JDK internal API
sun.reflect.Reflection.getCallerClass(int depth)
. This JEP proposes to define a standard API for stack walking that will be efficient and performant and also enable the implementation up level the stack walk machinery from the VM to Java and replaces the current mechanism ofThrowable.fillInStackTrace._ _Description_ _-----------_ _There is no standard API to traverse certain frames on the execution_ _stack efficiently and access the Class instance of each frame._ _There are APIs that allow to access the stack trace information:_ _-
Throwable.getStackTrace()and
Thread.getStackTrace()that_ _returns_ _an array of
StackTraceElementwhich contains the classname_ _and method name of a stack trace._ _-
SecurityManager.getClassContext()which is a protected method_ _such that only
SecurityManagersubclass can access the class_ _context._ _These APIs require the VM to eagerly capture a snapshot of the entire_ _stack trace and returns the information representing the entire stack._ _There is no other way to avoid the cost to examine all frames if_ _the caller is only interested in the top few frames on the stack._ _Both
Throwable.getStackTrace()and
Thread.getStackTrace()methods_ _return an array of
StackTraceElementthat contains the classname and_ _method name of a stack frame but the
Classinstance._ _In fact, for applications interested in the entire stack, the_ _specification_ _allows VM implementation to omit some frames in the stack for_ _performance._ _In other words,
Thread.getStackTrace()may return a partial stack_ _trace._ _These APIs do not satisfy the use cases that currently depend on_ _the
getCallerClass(int depth)method or its performance overhead_ _is intolerable. The use cases include:_ _- JDK caller-sensitive APIs look up its immediate caller's class_ _which will be used to determine the behavior of the API. For_ _example_ _
Class.forName(String classname)and_ _
ResourceBundle.getBundle(String rbname)methods use the_ _immediate_ _caller's class loader to load a class and a resource bundle_ _respectively._ _
Class.getMethodetc will use the immediate caller's class_ _loader_ _to determine the security checks to be performed._ _-
java.util.logging, Log4j and Groovy runtime filter the_ _intermediary_ _stack frames (typically implementation-specific and reflection_ _frames)_ _and find the caller's class to be used by the runtime of such_ _library_ _or framework._ _- Traverse the entire stack trace or the stack trace of a_ _
Throwbale_ _and obtain additional information about classes for enhanced_ _diagnosibility in addition to the class and method name._ _This JEP will define a stack walk API that allows laziness, frame_ _filtering,_ _supports short reaches to stop at a frame matching some criteria_ _as well as long reaches to traverse the entire stack trace. This would_ _need the JVM to provide a flexible mechanism to traverse and_ _materialize_ _the specific stack frame information to be used and allow efficient_ _lazy access to additional stack frames when required._ _Native JVM transitions should be minimzed._ _The API will define how it works when running with a security manager_ _that allows access to a
Classinstance_ _of any frame ensuring that the security is not compromised._ _An example API to walk the stack can be like:_ _Thread.walkStack(Consumer<StackFrameInfo> action, int depthLimit)_ _that takes a callback to be invoked for each frame traversed. A_ _variant_ _of the walkStack method will take a predicate for stack frame_ _filtering._ _Thread.getCaller(Function<StackFrameInfo, R> function)_ _Thread.findCaller(Predicate<StackFrameInfo> predicate,_ _Function<StackFrameInfo, R> function)_ _finds the caller frame with or without filtering._ _Testing_ _-------_ _Unit tests and JCK tests for the new SE API will need to be developed._ _In addition, the performance of the new API for different use cases_ _will be assessed._ _Impact_ _------_ _- Performance/scalability: performance measurement shall be_ _performed_ _using micro-benchmarks as well as real world usage of_ _
getCallerClass` replaced with the new API. - TCK: New JCK test cases shall be developed.
- Previous message: Draft JEP: Efficient Stack Walking API
- Next message: RFR [8035975] Pattern.compile(String, int) fails to throw IllegalArgumentException
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]