我最近一直在研究基准测试,我一直对记录程序数据等感兴趣。我有兴趣知道我们是否可以实现自己的内存使用代码并在我们的程序中有效地实现我们自己的时间消耗代码。我知道如何检查代码运行所需的时间:
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程序中是否可以实现高效的基准测试代码?
答案 0 :(得分:11)
是的,可以在java代码中有效地实现性能基准测试。重要的问题是,任何类型的性能基准测试都会增加自己的开销,以及您想要多少。 System.currentMill ..()是性能良好的基准,在大多数情况下,nanoTime()是一种过度杀伤。
对于内存System.gc将显示不同运行的不同结果(因为gc run从不保证。)我通常使用Visual VM进行内存分析(免费),然后使用TDA进行转储分析。
一种较少侵入性的方法是使用面向方面的编程。您可以只创建一个在特定注释或方法集上运行的Aspect,并编写@Around建议来收集性能数据。
这是一个小片段:
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
}
}
答案 1 :(得分:3)
如果没有一些海森堡效应,也可能无法进行基准测试,即您的长凳代码也在测量中。但是,如果您以足够高的粒度进行测量,则效果可以忽略不计。
答案 2 :(得分:2)
任何基准测试代码的效率都低于非基准测试代码,只是基于有更多的事情要做。也就是说,Java特别会引起问题,因为文章指出由于垃圾收集发生,只要jre感觉如此。甚至System.gc的文档也说它是“尽力而为”。
至于你的具体问题:
System.gc不应占用更多内存,但需要处理器资源。
根据您尝试的基准测试,这有点可能。总会有一些干扰。如果您愿意使用代码,可以使用VisualVM之类的工具来监视应用程序外部的内存使用情况。
编辑:更正了System.gc文档所说的措辞。