今天我做了一点快速Benchmark来测试System.nanoTime()
和System.currentTimeMillis()
的速度表现:
long startTime = System.nanoTime();
for(int i = 0; i < 1000000; i++) {
long test = System.nanoTime();
}
long endTime = System.nanoTime();
System.out.println("Total time: "+(endTime-startTime));
结果如下:
System.currentTimeMillis(): average of 12.7836022 / function call
System.nanoTime(): average of 34.6395674 / function call
为什么跑步速度的差异如此之大?
基准系统:
Java 1.7.0_25
Windows 8 64-bit
CPU: AMD FX-6100
答案 0 :(得分:65)
System.currentTimeMillis()
是使用。实现的 GetSystemTimeAsFileTime方法,它基本上只读取低 Windows维护的解析时间值。读这个 全局变量自然很快 - 大约6个周期 报道的信息。
System.nanoTime()
是使用。实现的QueryPerformanceCounter/ QueryPerformanceFrequency API
(如果有的话, 否则返回currentTimeMillis*10^6)
。QueryPerformanceCounter(QPC)
以不同方式实施 取决于它运行的硬件。通常它会使用 可编程间隔定时器(PIT)或ACPI电源 管理定时器(PMT)或CPU级时间戳计数器(TSC)。 访问PIT / PMT需要执行慢速I / O端口指令 因此,QPC的执行时间大约为 微秒。相反,读取TSC大约为100个时钟 循环(从芯片读取TSC并将其转换为时间值 根据工作频率而定。)
也许这回答了这个问题。这两种方法使用不同数量的时钟周期,从而导致后者的速度变慢。
进一步在结论部分的博客中:
如果您对测量/计算已用时间感兴趣,请始终使用System.nanoTime()。在大多数系统上,它将提供微秒级的分辨率。但请注意,此调用在某些平台上也可能需要几微秒才能执行。
答案 1 :(得分:24)
大多数操作系统(你没有提到你正在使用哪一个)都有一个内存计数器/时钟,它提供毫秒精度(或接近于此)。对于纳秒精度,大多数必须读取硬件计数器。与硬件通信比读取内存中的某些值要慢。
答案 2 :(得分:4)
可能只在Windows上出现这种情况。有关类似问题,请参阅this answer。
基本上,System.currentTimeMillis()
只读取由Windows维护的全局变量(它具有低粒度),而System.nanoTime()
实际上必须执行IO操作。
答案 3 :(得分:1)
你在Windows上测量它,不是你。我在2008年进行了这个练习。在Windows上,nanoTime比currentTimeMillis慢。我记得,在Linux上,nanime比currentTimeMillis更快,并且肯定比在Windows上更快。
需要注意的重要一点是,如果您要测量多个亚毫秒操作的聚合,则必须使用纳米时间,就像操作在不到1/1000秒的代码中完成一样,比较currentTimeMillis将显示瞬间操作,因此其中1,000个仍然是瞬时的。您可能想要做的是使用纳米时间然后舍入到最接近的毫秒,因此如果操作需要8000纳秒,它将被计为1毫秒,而不是0。