【发布时间】:2018-07-26 10:24:51
【问题描述】:
我正在制作一种概率模拟器,它将运行一定时间或一定数量的重复。我正在寻找优化它,它目前是多线程的,每个ProbabilityWorker 扩展Thread,主程序将自动分配n 线程,其中n 是但是许多线程可用(例如:on我的 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计算出来的。
另外,在同一个 Core 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()更适合您的目的(确定某事需要多长时间)。另请参阅Time measuring overhead in Java。 -
您可以检查一秒钟内完成了多少次操作,并检查任何 N 次操作的时间。您可能会在这里或那里失去半秒,但它会有所改善;)例如,如果您的目标是数百万,您可以每 50k 次尝试进行一次计时检查。它将是:while(您的条件){ for 1:50000 { do that operations } }
-
您在循环中调用
System.currentTimeMillis()283130850 次?我真的认为有更好的方法 - 实现tick并选择何时要检查给定时间小于当前时间。 -
“我用来获取当前时间相对于结束时间的开销很大” - 定义开销;这就是所谓的“忙循环”,即在分配的 CPU 时间允许的范围内调用多次的循环。您可能想要引入对 Thread.sleep() 的调用,以使该循环减少 CPU 占用 - 并减少同时完成的方法调用量。
-
生成一个随机整数比 currentTimeMillis() 要昂贵得多。尝试分析您的代码。
标签: java performance optimization