11

我有一个数独求解算法,我的目标是尽可能快地完成它。为了测试这个算法,我多次运行它并计算平均值。在注意到一些奇怪的数字后,我决定一直打印并得到以下结果:

Execution Time : 4.257746 ms (#1)
Execution Time : 7.610686 ms (#2)
Execution Time : 6.277609 ms (#3)
Execution Time : 7.595707 ms (#4)
Execution Time : 7.610131 ms (#5)
Execution Time : 5.011104 ms (#6)
Execution Time : 3.970937 ms (#7)
Execution Time : 3.923783 ms (#8)
Execution Time : 4.070238 ms (#9)
Execution Time : 4.765347 ms (#10)
Execution Time : 0.818264 ms (#11)
Execution Time : 0.620216 ms (#12)
Execution Time : 0.679021 ms (#13)
Execution Time : 0.643516 ms (#14)
Execution Time : 0.718408 ms (#15)
Execution Time : 0.744481 ms (#16)
Execution Time : 0.760569 ms (#17)
Execution Time : 0.80384 ms (#18)
Execution Time : 0.75946 ms (#19)
Execution Time : 0.802176 ms (#20)
Execution Time : 66.032508 ms : average = 3.3016254000000003

执行 10 到 15 次后(随机变化),算法的性能显着提高。如果我运行它几百次,它最终会稳定在 0.3ms 左右。请注意,我在此循环之前运行了一次算法,以便 JIT 执行此操作。

此外,如果我在运行循环之前让线程休眠 2 秒,那么我所有的时间都是 1 毫秒(+/- 0.2)。

此外,如果我在循环之前解决了大约 500 次通用数独(对角线为 1-9 的网格),我所有的时间都在 0.3 毫秒左右(+/- 0.02)。

每个解决方案都是相同的。所有值都被重置。

所以我的问题是多方面的:

- 为什么在连续解决后每次解决时间都会提高?

- 为什么在 10-15 次解决后我的解决时间突然下降?

4

2 回答 2

14

这是因为在对该方法进行一定次数的频繁调用JIT后编译该方法。JVM在实践中,方法在第一次被调用时不会被编译。对于每个方法,JVM 维护一个调用计数,每次调用该方法时都会递增。JVM 解释一个方法,直到它的调用计数超过一个JIT compilation threshold. 当调用计数达到阈值时,JIT编译和优化它,bytecodes以便在下次调用时运行得更快JVM。因此,在您的情况下,每执行 10 到 15 次(随机),算法的性能就会显着提高。

于 2013-06-06T19:15:01.940 回答
2

最有可能 - JVM 在多次运行后优化了它的执行。

除此之外,应用程序本身可以做一些改进执行结果的事情。

在不详细了解您运行的内容的情况下,很难说得更准确。

您是否使用外部资源 - 数据库连接、JMS 队列/主题等?你使用缓存吗?

一切都很重要...

于 2013-06-06T19:07:44.963 回答