很多时候在编写应用程序时,我希望在 stacktrace 中分析和测量所有方法所花费的时间。我的意思是说:
Method A --> Method B --> Method C ...
A
方法在内部调用 B
并且它可能会调用另一个。我想知道在每个方法中执行所花费的时间。这样,在 Web 应用程序中,我可以准确地知道代码的哪一部分所消耗的时间百分比。
为了进一步解释,在大多数情况下,在 spring 应用程序中,我编写了一个方面,用于收集类的每个方法调用的信息。最后给了我总结。但我讨厌这样做,它重复且冗长,并且需要不断更改正则表达式以适应不同的类。相反,我想要这样:
@Monitor
public void generateReport(int id){
...
}
在方法上添加一些注释将触发检测 api 来收集此方法所用时间的所有统计信息以及以后调用的任何方法。并且当该方法退出时,它停止收集信息。我认为这应该比较容易实现。
问题是:对于一般的 Java 代码,是否有任何合理的替代方案可以让我这样做?或者任何快速收集这些信息的方法。或者甚至是用于 spring 应用程序的 spring 插件?
PS:一模一样XRebel ,它会生成代码的安全、DAO、服务等部分所用时间的精美摘要。但它要花一枚炸弹。如果负担得起,绝对应该购买。
最佳答案
你想写一个Java agent .这样的代理允许您在加载类时重新定义它。这样,您可以在不污染源代码的情况下实现一个方面。我写了一个图书馆,Byte Buddy ,这使得这相当容易。
对于您的监视器示例,您可以按如下方式使用 Byte Buddy:
new AgentBuilder.Default()
.rebase(declaresMethod(isAnnotatedWith(Monitor.class))
.transform( (builder, type) ->
builder
.method(isAnnotatedWith(Monitor.class))
.intercept(MethodDelegation.to(MonitorInterceptor.class);
);
class MonitorInterceptor {
@RuntimeType
Object intercept(@Origin String method,
@SuperCall Callable<?> zuper)
throws Exception {
long start = System.currentTimeMillis();
try {
return zuper.call();
} finally {
System.out.println(method + " took " + (System.currentTimeMillis() - start);
}
}
}
上面构建的代理可以安装在提供给任何 Java 代理的检测接口(interface)实例上。
与使用 Spring 相比,上述代理将适用于任何 Java 实例,而不仅仅是 Spring bean。
关于java - 执行方法栈中所有方法所花费的时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29987725/