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