【问题标题】:Benchmarking inside Java code在 Java 代码中进行基准测试
【发布时间】:2012-01-15 11:08:52
【问题描述】:

我最近一直在研究基准测试,我一直对记录程序数据等感兴趣。我很想知道我们是否可以在我们的程序中实现我们自己的内存使用代码并有效地实现我们自己的时间消耗代码。我知道如何检查代码运行所需的时间:

public static void main(String[]args){
        long start = System.currentTimeMillis();
        // code
        System.out.println(System.currentTimeMillis() - start);
    }

我也看了Robust Java benchmarking, Part 1: Issues,这个教程很全面。显示System.currentTimeMillis(); 的负面影响。然后教程建议我们使用System.nanoTime();(让它更准确?)。

我还查看了Determining Memory Usage in Java 的内存使用情况。该网站显示了如何实施它。提供的代码看起来效率低下,因为该人正在调用

long L = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

在此之后,他调用System.gc(); (4 * 4) = 16 次。然后再次重复该过程。 这不也占内存吗?

总之,是否有可能在您的 java 程序中实现有效的基准测试代码?

【问题讨论】:

标签: java performance benchmarking


【解决方案1】:

是的,可以在 java 代码中有效地实现性能基准。重要的问题是任何类型的性能基准都会增加自己的开销以及您想要多少。 System.currentMill..() 对于性能来说已经足够好了,而且在大多数情况下 nanoTime() 是多余的。

对于内存 System.gc 将显示不同运行的不同结果(因为 gc 运行从不保证。)我通常使用 Visual VM 进行内存分析(它是免费的),然后使用 TDA 进行转储分析。

减少侵入性的一种方法是使用面向方面的编程。您可以只创建一个在特定 Annotation 或一组方法上运行的 Aspect,并编写一个 @Around 建议来收集性能数据。

这是一个小sn-p:

public class TestAspect {

    @LogPerformance
    public void thisMethodNeedsToBeMonitored(){
        // Do Something
    }
    public void thisMethodNeedsToBeMonitoredToo(){
        // Do Something
    } 
}

@interface LogPerformance{}

@Aspect
class PerformanceAspect{
    @Around("the pointcut expression to pick up all " +
            "the @PerfMonitor annotated methods")
    public void logPerformance(){
        // log performance here
        // Log it to a file
    }
}

【讨论】:

  • 我不知道 nanoTime() 会花费更长的时间,而且它肯定更准确。在许多情况下 currentTimeMillis() 是完全不够的。只是总是使用 nanoTime()
【解决方案2】:

如果没有一些海森堡效应,可能无法进行基准测试,即您的基准代码也会被测量。但是,如果您以足够高的粒度进行测量,则影响可以忽略不计。

【讨论】:

  • 这里是否可以应用海森堡原理并不完全清楚。该原理指出,如果提高测量一种属性的精度,例如通过从currentTimeMillis 切换到nanoTime(),第二个属性将变得不那么精确。在测量 Java 方法(方法开始时间和结束时间之间的增量)的情况下,第二个属性是什么?
【解决方案3】:

任何基准测试代码的效率都会低于非基准测试代码,因为有更多的事情要做。也就是说,正如文章所述,Java 尤其会引起问题,因为每当 jre 感觉像它时就会发生垃圾收集。甚至 System.gc 的文档也说它“尽最大努力”。

至于你的具体问题:

System.gc 不应占用更多内存,但会占用处理器资源。

根据您要进行基准测试的内容,这在一定程度上是可能的。总会有一些干扰。如果您愿意跳出代码之外,可以使用 VisualVM 等工具从应用程序外部观察内存使用情况。

编辑:更正了 System.gc 文档所说的措辞。

【讨论】:

    猜你喜欢
    • 2013-03-10
    • 2014-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-25
    • 1970-01-01
    相关资源
    最近更新 更多