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.bate...@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

Reply via email to