8205132: Remove Thread.countStackFrames()
Mandy Chung
mandy.chung at oracle.com
Thu Oct 24 19:34:13 UTC 2019
There is cost to examine the stack frames. The StackWalker API allows
you to fetch the stack frames one batch at a time to avoid unnecessary
deoptimization to frames that are not traversed. In addition,it can
specify to include/exclude the hidden frames and/or reflection
implementation-specific frames.
It is true that there is more setup to do for StackWalker to count the
frames. It's possible to provide a specialized stack walker
implementation to optimize getting the stack depth where the object
allocation can be eliminated (e.g. StackWalker::getCallerClass uses a
specialized implementation for performance). However, the stack depth
is just a workaround for you.
BTW, you can call Stream::count to count the stack frames:
StackWalker.getInstance().walk(s -> { return s.count(); })
Mandy
On 10/24/19 9:32 AM, seth lytle wrote:
> The use case that's always interested me is checking to see if a
> callback to a recursive method (eg during parsing) is "too deep" so
> you can bail out (eg, to a non-recursive one or using message
> passing). For that purpose, it's already suspended and the native
> method is close to what I'd like if it wasn't deprecated.
>
> You started this discussion by claiming that "The StackWalker API is a
> much better solution for code that is interested in the number of
> stack frames". Seems like a benchmark is a critical part of that
> claim. The stack walker approach looked 8x-ish slower for deep stacks
> (eg, 1000 and 5000), which is about what I expected given all the
> unnecessary object allocations. The walker API also seemed more prone
> to stack overflows, but I didn't take the time to quantify that.
> Here's one example run (java 11 with defaults):
>
> Benchmark (stackDepth) Mode Cnt Score Error Units
> StackWalkerJmh.count 1000 avgt 3 0.030 ± 0.002 ms/op
> StackWalkerJmh.count 5000 avgt 3 0.151 ± 0.015 ms/op
>
>
> Benchmark (stackDepth) Mode Cnt Score Error Units
> StackWalkerJmh.walk 1000 avgt 3 0.261 ± 0.027 ms/op
> StackWalkerJmh.walk 5000 avgt 3 1.313 ± 1.131 ms/op
>
>
> @Benchmark
> public int walk() { return recStackWalker(stackDepth); }
> private static int recStackWalker(int depth) {
> return depth == 0 ? getWalker() : recStackWalker(depth-1);
> }
> private static int getWalker() {
> Count cc = new Count();
> StackWalker.getInstance().forEach(x -> cc.count++);
> return cc.count;
> }
> static class Count { int count; }
> @Benchmark
> public int count() { return recStackTrace(stackDepth); }
> private static int recStackTrace(int depth) {
> return depth == 0 ? getDepth() : recStackTrace(depth-1);
> }
> private static int getDepth() {
> return Thread.currentThread().countStackFrames();
> }
>
>
>
> What would be even more useful than stack depth would be an estimate
> of the number of bytes remaining in the stack, esp if it was fast. Any
> chance that that could get added to the stack walker API ?
>
>
>
>
>
>
>
>
>
> On Thu, Oct 24, 2019 at 4:21 AM Alan Bateman <Alan.Bateman at oracle.com> wrote:
>> On 23/10/2019 23:00, seth lytle wrote:
>>> At least a couple appear to be recently active, though I don't have
>>> current access. Maybe an IDE generates boilerplate for proxies and
>>> ignores deprecation ?
>>>
>>> is the speed of the StackWalker approach to counting frames comparable
>>> to the current native method ?
>>>
>> countStackFrames has always been ill-defined, and it requires the thread
>> to be suspended. We've been directly people to StackWalker and several
>> releases so best to try it yourself and come back with your results/issues.
>>
>> -Alan
More information about the core-libs-dev
mailing list