我正在制作一种概率模拟器,该模拟器可以运行一定的时间,也可以运行一定的重复次数。我正在对其进行优化,并且当前每个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;
}

如果重复运行一定数量,则modetruerandy是Random,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 (并坚持使用)-这是您在JVM AFAIK中可以得到的最好的结果。除了它可以测量耗时而没有时钟时间的概念外,它也是最快的-这就是JMH使用它的原因(或我希望的其他任何合理的微基准测试)。

除了System.currentTimeMillis返回ms精度的事实(并且某些事情的完成速度比1ms更快)之外,两次调用此方法can return a negative value的区别。

不过,有两点要记住,首先是对System.nanoTime的每次调用也具有性能影响,平均而言,每个调用平均需要25 ns(就我而言,它接近于您的CPU和JVM-9)。

最后一点是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/

10-11 04:46
查看更多