Closed as not planned
Description
Recently I am learning new features after jdk9, I saw an interesting feature. Stack-Walking API.
This API allows us to iterator the current stack in a streaming fashion. So I want to use this method to rewrite the deduceMainApplicationClass method. This will make the code look more concise.
This method can be optimized like this:
return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
.walk((s) -> s.filter(e -> e.getMethodName().equals("main")).findFirst().map(
StackWalker.StackFrame::getDeclaringClass))
.orElseThrow(ClassNotFoundException::new);
JMH demo
package com.ggggght.jmh;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
@Fork(2) @Warmup(iterations = 1, time = 1) @State(Scope.Benchmark)
@BenchmarkMode(value = {Mode.Throughput}) public class StackWalkBench {
private static final StackDriver STACK_DRIVER = new StackDriver();
@Param({"50", "100", "200"}) private int initialDepth;
@Param({"10", "20"}) private int callDepth;
@Benchmark() public void stackWalkWalk() {
StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
List<StackTraceElement> stackTraceElements = walker.walk(
stackFrameStream -> stackFrameStream.map(StackWalker.StackFrame::toStackTraceElement)
.collect(Collectors.toList()));
STACK_DRIVER.deepCall(initialDepth, callDepth, FQCN -> walker.walk(
s -> s.dropWhile(f -> !f.getClassName().equals(FQCN))
.dropWhile(f -> f.getClassName().equals(FQCN))
.findFirst()).get().toStackTraceElement());
}
@Benchmark() public void throwableSearch() {
STACK_DRIVER.deepCall(initialDepth, callDepth, FQCN -> {
StackTraceElement[] stackTrace = new Throwable().getStackTrace();
boolean found = false;
for (int i = 0; i < stackTrace.length; i++) {
String className = stackTrace[i].getClassName();
if (FQCN.equals(className)) {
found = true;
continue;
}
if (found && !FQCN.equals(className)) {
return stackTrace[i];
}
}
return null;
});
}
public static void main(String[] args) throws RunnerException {
Options opt =
new OptionsBuilder().include(StackWalkBench.class.getSimpleName()).build();
new Runner(opt).run();
}
}
class StackDriver {
public StackTraceElement deepCall(int initialDepth, int targetDepth,
Function<String, StackTraceElement> supplier) {
if (--initialDepth == 0) {
Processor processor = new Processor();
return processor.apply(targetDepth, supplier);
}
return deepCall(initialDepth, targetDepth, supplier);
}
private static class Processor
implements BiFunction<Integer, Function<String, StackTraceElement>, StackTraceElement> {
private static final String FQCN = Processor.class.getName();
@Override public StackTraceElement apply(Integer depth,
Function<String, StackTraceElement> function) {
if (--depth == 0) {
return function.apply(FQCN);
}
return apply(depth, function);
}
}
}
Here are the results of a benchmark I did with hotspot17 and jmh. The complete information I put in the file below.