如何衡量用 Java 编写的代码的速度?
我计划开发一个软件,它将使用所有目前可用的 AI 和 ML 算法来解决数独问题,并将运行时间与简单的暴力破解方法进行比较。我需要测量每种算法的运行时间,我想请教一下衡量时间的最佳方法是什么?非常重要的一点是,该程序必须在任何机器上都能正常运行,而与 CPU 性能/内存无关。
谢谢。
回答:
正如其他人建议的那样,System.currentTimeMillis()
相当不错,但请注意以下几点:
System.currentTimeMillis()
测量的是经过的物理时间(“挂钟时间”),而不是 CPU 时间。 如果机器上运行着其他应用程序,您的代码将获得更少的 CPU 时间,其速度也会降低。 因此,最好仅在空闲系统上进行基准测试。- 类似地,多核系统上的多线程应用程序可能会获得额外的、隐藏的 CPU 时间。 经过的时间测量无法捕捉多线程应用程序的全部复杂性。
- Java 需要一些“预热”时间。 虚拟机将首先解释代码(这很慢),并且,如果某个给定的方法被使用太多次,则 JIT 编译器会将该方法转换为本机代码。 只有在那时,该方法才能达到其最高速度。 我建议您在调用
System.currentTimeMillis()
之前执行几个“空循环”。 System.currentTimeMillis()
的精度很少能达到 1 毫秒。 在许多系统中,精度不会超过 10 毫秒,甚至更多。 此外,JVM 有时会运行 GC,从而导致明显的暂停。 我建议您在一个循环中组织您的测量,并坚持运行至少几秒钟。
这将产生以下代码:
for (int i = 0; i < 10; i ++) { runMethod();}int count = 10;for (;;) { long begin = System.currentTimeMillis(); for (int i = 0; i < count; i ++) runMethod(); long end = System.currentTimeMillis(); if ((end - begin) < 10000) { count *= 2; continue; } reportElapsedTime((double)(end - begin) / count);}
正如你所看到的,首先有十次“空”运行。 然后,程序在一个循环中运行该方法,次数尽可能多,以便该循环至少花费十秒钟。 十秒钟应该足以消除 GC 运行和其他系统不准确性。 当我测试哈希函数实现时,我使用两秒钟,即使该函数本身根本不会触发内存分配,我仍然会获得高达 3% 的变化。