Thread.getStackTrace() 有多贵?

2022-09-02 11:52:02

在日志记录系统中,每个日志输出都由帮助器类使用如下所示的方法完成

public void debug(String message) {
    Logger logger = Logger.getLogger(getCallingClass());
    logger.debug(message);
}
...
public Class getCallingClass() {
/*
Calls Thread.getStackTrace() and back traces until the class on the stack trace 
!= this.getClass(). 
*/
    return classFound;
}

运行成本有多高,它是否会对性能产生重大影响?


答案 1

现在有了JDK 9和10,你可以使用StackWalker,这不是一个昂贵的调用。

private void invoke006() {
        var stack = StackWalker.getInstance(StackWalker.Option.SHOW_HIDDEN_FRAMES).walk((s) -> s.collect(Collectors.toList()));
        stack.forEach(stackFrame -> {
            if (stackFrame.getMethodName().equals("masterInvoker")) {
                System.err.println("master called !!");
                System.err.println(StackWalker.getInstance().walk((s) -> s.collect(Collectors.toList())).get(0).getMethodName() + ", line: " + StackWalker.getInstance().walk((s) -> s.collect(Collectors.toList())).get(0).getLineNumber());
            }
        });
    }

答案 2

是的,此调用有一些开销,但很可能,您将执行如下操作:

public static boolean DEBUG_ON = true; //change this before your production build

然后

public void debug(String message){
  if(DEBUG_ON){
     //stack code here
  }

}

这将导致您在实际代码中不会受到打击。

即使这样,对于异常,您也会在生产构建中抛出整个堆栈跟踪异常。

请注意,如果您使用的是一个体面的日志记录子系统,他们可能已经根据日志记录级别执行了一些操作(在我们的日志系统中,取决于级别,debug()基本上是一个no-op)。Log4j和其他人有不同的处理方式。

最后,我想说的是:在它被证明是一个真正的性能问题之前,不要担心它。过早优化是所有邪恶:)


推荐