Draft JEP: Efficient Stack Walking API (original) (raw)
David M. Lloyd david.lloyd at redhat.com
Wed Jul 9 13:42:42 UTC 2014
- Previous message: Draft JEP: Efficient Stack Walking API
- Next message: Draft JEP: Efficient Stack Walking API
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Just want to say that I am also looking forward to progress on this.
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 of Throwable.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.
>>>>>>>>>>
- DML
- Previous message: Draft JEP: Efficient Stack Walking API
- Next message: Draft JEP: Efficient Stack Walking API
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]