2

我正在尝试使用计时器来测量算法的复杂性来测量执行时间,同时改变输入数组的大小。

我现在的代码相当简单:

public void start() {
    start = System.nanoTime();
}

public long stop() {
    long time = System.nanoTime() - start;
    start = 0;
    return time;
}

它似乎工作正常,直到数组的大小变得非常大,而我期望的 O(n) 复杂度算法结果似乎是 O(n^2)。我相信这是由于 CPU 上的线程,其他进程在运行期间切入更多时间,n 值更大。

基本上,我想测量我的进程运行了多少时间,而不是我调用算法以来已经运行了多长时间。有没有一种简单的方法可以在 Java 中做到这一点?

4

3 回答 3

3

测量执行时间是一个非常有趣但也很复杂的话题。要在 Java 中正确执行此操作,您必须对 JVM 的工作原理有所了解。是 developerWorks 上一篇关于基准测试和测量的好文章。阅读它,它会帮助你很多。

作者还提供了一个做基准测试的小框架。你可以使用这个框架。它将为您提供所需的确切信息 - CPU 消耗时间,而不仅仅是之前和之后的两个时间戳。该框架还将处理 JVM 预热并跟踪即时编译。

您还可以为 Eclipse使用像这样的性能监视器。这种性能监视器的问题是,它不执行基准测试。它只是跟踪您的应用程序当前使用的时间、内存和诸如此类的东西。但这不是真正的测量——它只是特定时间的快照。

于 2012-05-05T16:42:13.343 回答
1

Java 中的基准测试是一个难题,尤其是因为随着您的方法得到越来越多的优化,JIT 可能会产生奇怪的效果。考虑使用像Caliper这样的专用工具。有关如何使用它以及测量不同输入大小的性能的示例,请参见此处

于 2012-05-05T16:40:28.377 回答
1

如果您想要当前线程(或者实际上是任意线程)的实际 CPU 时间而不是挂钟时间,那么您可以通过 ThreadMXBean 获得它。基本上,一开始就这样做:

ThreadMXBean thx = ManagementFactory.getThreadMXBean();
thx.setThreadCpuTimeEnabled(true);

然后,每当您想获取当前线程的经过 CPU 时间时:

long cpuTime = thx.getCurrentThreadCpuTime();

您会看到 ThreadMXBean 也有调用来获取 CPU 时间和任意线程的其他信息。

关于时间复杂性的其他评论也适用。单独调用一段代码的时间可能取决于 CPU 的状态以及 JIT 编译器在该特定时刻决定执行的操作。算法的整体可扩展性行为通常是在多次调用中出现的趋势,您总是需要为时间安排中的一些“异常值”做好准备。

另外,请记住,仅仅因为特定时间以纳秒(或实际上是毫秒)表示,并不意味着该时间实际上具有该粒度。

于 2012-05-05T16:54:23.993 回答