System.getCurrentTimeMillis()的性能开销

DDP*_*AGE 6 java optimization performance

我正在制作一种概率模拟器,它可以运行一定的时间,也可以进行一定的重复次数.我正在寻求优化它,它目前是多线程的,每个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;
}
Run Code Online (Sandbox Code Playgroud)

其中modetrue如果重复的量运行,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)
Run Code Online (Sandbox Code Playgroud)

我的问题是,有没有办法优化System.currentTimeMillis()调用,或者没有它或减少需要多少时间?我可以使用另一个更快的通话吗?

Eug*_*ene 3

你真的应该研究一下System.nanoTime(并坚持下去)——据我所知,这是你在 JVM 中能得到的最好的结果。除了它在没有任何时钟时间概念的情况下测量经过的时间这一事实之外,它也是最快的 - 这就是JMH使用它的原因(或我希望的任何其他合理的微基准)。

除了System.currentTimeMillis返回ms精度(并且有些事情完成得比 更快1ms)之外,对此方法的两次调用之间的差异可能会返回负值

不过,有两件事需要记住,首先是每次调用也会System.nanoTime对性能产生影响,平均每次调用都会花费(在我看来,接近您的 CPU 和 JVM-9)25 ns

最后一点是System.nanoTime有纳秒精度,但不是纳秒精度。这意味着当您致电时:

long start = System.nanoTime();
long end = System.nanoTime();
Run Code Online (Sandbox Code Playgroud)

两个结果都将返回一个具有纳秒精度的数字,即它们将具有多个数字。

但这个数字不可能非常准确。嗯,根据你的要求准确。由于System.nanoTime返回一个任意值,因此没有任何东西可以与它进行比较,除非其他调用System.nanoTime,因此:

long result = end - start;
Run Code Online (Sandbox Code Playgroud)

是/可能不会是纳秒级的精确结果。其误差约为 1 微秒,在我的笔记本电脑上约为 0.2-0.5 微秒。


使用System.nanoTime,没有比这更快或更细粒度的东西了。