我正在制作一种概率模拟器,它将运行一定的时间或一定的重复次数。我想优化一下,目前是多线程的,每个ProbabilityWorker
扩展Thread
,主程序会自动分配n
个线程,其中 n
是但是有很多线程可用(例如:在我的 Core i3-7100U 上,这是 4)。
我正在分析它的性能,我意识到我用来获取相对于结束时间的当前时间的方法会导致大量开销。
对于它可以“运行一定时间”的模式,我将 new Date
对象作为循环条件的一部分,然后我将其更改为更快的 System.currentTimeMillis()
试图节省时间,但我注意到即使这样也会产生开销。
我的 run
函数如下所示:
public void run() {
if (mode) {
while (completed < repitions) {
resultSet[randy.nextInt(o)]++;
completed++;
}
} else {
while (System.currentTimeMillis() < endTime) {
resultSet[randy.nextInt(o)]++;
completed++;
}
}
done = true;
}
其中 mode
为 true
如果运行一定数量的重复,randy
为随机数,o
为可能结果的数量,endTime
是结束点,以毫秒为单位,系统时间(可以修改,程序占用秒数,endTime
是通过以下方式计算的当前时间加上 secondsInput * 1000
)。
此外,在同一个酷睿 i3-7100U 上,这些是我的性能统计数据:
DE-WEY-LAPTOP:/mnt/c/Users/danny/Documents/Programming/Data Structures/Probability$ java Main -n 10000000000
Running 10000000000 repitions of the probability simulator with 2 possible outcomes.
4 threads detected on system; doing 2500000000 repitions per thread.
Done. Gathering results from worker threads...
Done. Printing results...
Outcome 1: 4999997330 out of 10000000000 (49.9999733%)
Outcome 2: 5000002670 out of 10000000000 (50.0000267%)
Time taken: 43.443 seconds (2.301866813986143E8 ops/sec)
DE-WEY-LAPTOP:/mnt/c/Users/danny/Documents/Programming/Data Structures/Probability$ java Main -t 44
Running the probability simulator for 44 seconds using 4 threads.
Done. Gathering results from worker threads...
Done. Printing results...
Outcome 1: 141568074 out of 283130850 (50.000935609807264%)
Outcome 2: 141562776 out of 283130850 (49.999064390192736%)
Time taken: 44 seconds (6434792.045454546 ops/sec)
我的问题是,是否有一种方法可以优化 System.currentTimeMillis()
调用,使其不存在或减少所需时间?我可以使用另一个更快的调用吗?
最佳答案
你真的应该调查System.nanoTime
(并坚持下去)——这是你在 JVM AFAIK 中可以获得的最好的。除了它在没有任何时钟时间概念的情况下测量耗时这一事实之外,它也是最快的 - 这就是原因 JMH使用它(或我希望的任何其他理智的微基准)。
除了 System.currentTimeMillis
返回 ms
精度这一事实(有些事情的完成速度比 1ms
快),两者之间的区别两次调用此方法 can return a negative value .
但有两件事要记住,首先是每次调用 System.nanoTime
也有性能影响,平均而言它需要(在我的,接近你的 CPU 和 JVM -9) 25 ns
每次调用。
最后一点是 System.nanoTime
具有纳秒级精度,但不是纳秒级精度。这意味着当你打电话时:
long start = System.nanoTime();
long end = System.nanoTime();
这两个结果都将返回一个具有纳秒级精度的数字,即它们将有多个数字。
但是这个数字不可能很准确。好吧,根据你可能会问的准确。由于 System.nanoTime
返回一个任意值,因此没有什么可以与之比较,除非对 System.nanoTime
的其他调用,因此:
long result = end - start;
是/可能不会是纳秒级的精确结果。这个误差大约为 1 微秒,在我的笔记本电脑上大约为 0.2-0.5 微秒。
使用 System.nanoTime
,没有比这更快或更细粒度的了。
关于java - System.getCurrentTimeMillis() 的性能开销,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48811036/