自动比较单元测试的Java性能分析结果

8

我想运行一个单元测试,并收集它的“分析”信息:每个方法被调用的频率,某些类的实例创建了多少个,执行某个方法/线程花费了多少时间等等。然后,我想将这些信息与一些期望值进行比较。是否有Java的分析工具可以让我自动完成所有这些操作(当然不需要任何GUI或用户交互)?

以下是我希望它工作的方式:

public class MyTest {
  @Test
  public void justTwoCallsToFoo() {
    Profiler.start(Foo.class);
    Foo foo = new Foo();
    foo.someMethodToProfile(); // profiler should collect data here
    assertThat(
      Profiler.getTotalCallsMadeTo(Foo.class, "barMethod"), 
      equalTo(3)
    );
  }
}

这个问题与SO上的其他“你能推荐一个Java分析器吗?”问题有何不同?我使用Intellij和YourKit,只需像任何其他运行一样对(单独的)单元测试进行分析即可... - amaidment
1
我想在单元测试中对一个类/方法进行性能分析 - 不使用任何IDE或与性能分析器的任何可视化交互。 - yegor256
你的意思是说,你的单元测试将执行分析器,收集输出,并根据分析数据(例如,方法被调用的次数)来判断单元测试是否通过/失败?如果是这样,那么我认为问题可以澄清一下,明确你想要通过API编程方式调用分析器并获取其输出。例如,我理解“我想比较”是指你手动进行比较。 - Andrzej Doyle
@AndrzejDoyle 我已经更新了问题,并提供了一个Java示例。 - yegor256
2个回答

3
自动捕获性能分析信息可以通过几个Java分析工具实现,您需要在Java启动命令中添加VM参数来加载分析工具,并告诉分析工具记录数据并在退出时保存快照。在JProfiler中,您可以使用"profile" ant task来实现此功能。它从JProfiler GUI导出的配置文件中获取分析设置。您可以使用Controller API启动记录并保存快照。然后您有两个选择:
  1. 您可以使用jpcompare命令行实用程序或相应的"比较" ant任务来将快照与已知基线进行比较。有几种比较可用。您可以将结果导出为HTML或机器可读格式(CSV/XML)。

  2. 您可以使用jpexport命令行实用程序或相应的"导出" ant任务从快照中提取数据。然后,您可以编写自己的代码来分析特定运行的分析数据。

对于有限的分析数据,实际上可以使用JProfiler API编写自己的分析器,例如在您的示例中使用Profiler.getTotalCallsMadeTo(Foo.class,“barMethod”)。请参阅JPofiler安装中的api/samples/platform示例。您将从热点数据中获取信息。
但是,为了对是否调用了特定方法进行断言,我建议采用基于AOP的方法。使用基于分析器的方法适用于检测性能回归。
免责声明:我的公司开发JProfiler。

听起来像是一个解决方案,谢谢。顺便问一下,你有Maven插件吗? - yegor256
不,我们还没有Maven插件。 - Ingo Kegel
另一个缺点是它不是免费产品。 - yegor256

2
我发现可以使用J2SE内置的HPROF profiling工具来完成这项工作。
java -agentlib:hprof=cpu=times MyTest

它会生成一个格式如下的文本文件:
CPU SAMPLES BEGIN (total = 126) Fri Oct 22 12:12:14 2004
rank   self  accum   count trace method
   1 53.17% 53.17%      67 300027 java.util.zip.ZipFile.getEntry
   2 17.46% 70.63%      22 300135 java.util.zip.ZipFile.getNextEntry
   3  5.56% 76.19%       7 300111 java.lang.ClassLoader.defineClass2
   4  3.97% 80.16%       5 300140 java.io.UnixFileSystem.list
   5  2.38% 82.54%       3 300149 java.lang.Shutdown.halt0
....

然后,解析文件并提取您感兴趣的方法就很容易了。该解决方案完全免费且内置于JSE中,与其他工具相比具有很大的优势。

看起来你提供的链接现在重定向到Oracle主页了... 你可能需要更新它为http://docs.oracle.com/javase/7/docs/technotes/samples/hprof.htmlm。 - evandor
自Java 8之后,hprof已不再可用。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接