从Java内部测量各个方法的性能的确切方法?

时间:2011-08-06 00:12:31

标签: java performance

我想测量一组单元测试的执行时间,以便能够在进行更改时自动监视和比较性能。是否有任何合适的性能计数器可以从Java本身轻松访问?即,像:

count1 = <call performance counter func>
executeUnitTest();
count2 = <call performance counter func>
testPerformance = count2 - count1;

有这些额外要求:

  • 提供与系统负载无关的相同答案,即使测试运行器在虚拟客户操作系统中运行(由于主机上的负载变化,这似乎取消了nanoTime()和朋友,甚至当前线程的cpu时间的资格)
  • 给出相同的答案,与运行的硬件无关(计算执行的字节码指令数量非常好!)
  • 理想情况下,可以将GC执行计数与实际方法执行分开(如果GC是在线程中完成的)

3 个答案:

答案 0 :(得分:2)

执行此操作的唯一方法是检测代码以添加独立于平台的计数器。您可以在任何有工作单位的地方添加代码。

如果您希望它是线程安全的,请使用AtomicLong / AtomicInteger。

 public static int counter;


 // instrumented into the code.
 counter++;

 // big piece of work
 counter+=5;

然后,您可以比较计数器的增加量。这将独立于CPU的速度,GC甚至在中间休眠应用程序可能无关紧要。


我将采用的方法是将许多结果与另一个我不希望改变的类似参考实现进行比较。您可以预期一定的比例,无论您使用何种平台,这个比例都只会有很小的变化。

答案 1 :(得分:1)

您可以考虑几种方法。

'检测'在编译或加载时发生,并改变类文件,以便它们保持计数器正在进行的操作。通常,这用于测量单元测试的代码覆盖率,但您可以修改代码覆盖率工具以保持执行计数。从内存来看,认为代码覆盖率工具Emma是一个很好的开源来源。由于GC没有检测,因此不会计算。可能会有一些开箱即用的东西。

分析工具可能至少可以为您提供一些您所追求的数据。有可用的堆,包括标准的'java'可执行文件,可以生成许多您可以使用的信息。

VM中还有相当复杂的分析钩子,API可以通过标准的JVMTI api访问,这是自IIRC 1.5标准API的一部分。

答案 2 :(得分:0)

您将无法获得准确的衡量标准(缺少运行整机模拟器等假设方法)。

所有实际方法都存在测量过程扭曲被测应用的行为的问题。例如,插入代码以捕获系统时钟之前和之后的时间可能会妨碍JIT编译器优化和改变存储器访问模式的能力。通过修改代码工作的分析工具也会遇到这个问题。通过对代码指针进行采样而工作的其他工具遇到的问题是它们需要大量样本才具有统计意义。

简而言之,虽然您可以通过临时测量和分析获得有用的结果,但结果需要花费一些时间。它们可能会产生误导,很容易被误解。

我建议您根据您的代码调优是否有助于使用实际工作负载进行大规模(系统级)基准测试,从而做出最终决策。