为什么System.nanoTime()方法比System.currentTimeMillis()更慢?

今天我做了一个快速的基准testing来testingSystem.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 

从这个Oracle博客 :

System.currentTimeMillis()是使用GetSystemTimeAsFileTime方法实现的,它基本上只读取Windows维护的低分辨率时间值。 根据所报告的信息,读取这个全局variables自然是非常快的 – 大约6个周期。

System.nanoTime()是使用QueryPerformanceCounter/ QueryPerformanceFrequency API (如果可用,否则返回currentTimeMillis*10^6)QueryPerformanceCounter(QPC)根据运行的硬件以不同的方式实现。 通常,它将使用可编程间隔定时器(PIT)或ACPI电源pipe理定时器(PMT),或CPU级别的时间戳计数器(TSC)。 访问PIT / PMT需要执行慢I / O端口指令,因此QPC的执行时间大约为几微秒。 相反,读取TSC的时间大约为100个时钟周期(从芯片读取TSC并将其转换为基于工作频率的时间值)。

也许这回答了这个问题。 这两种方法使用不同数量的时钟周期,从而导致后者的速度变慢。

进一步在结论部分的博客中:

如果您对测量/计算所用时间感兴趣,则始终使用System.nanoTime()。 在大多数系统上,它将提供微秒级的分辨率。 但请注意, 这个调用也可能需要几个微秒的时间才能在某些平台上执行

大多数操作系统(你没有提到你正在使用哪一个)有一个内存计数器/时钟,它提供了毫秒级的准确度(或接近于此)。 对于纳秒精度,大部分都必须读取硬件计数器。 与硬件通讯比较慢,因此读取内存中的某些值。

这可能只是在Windows上的情况。 看到这个答案类似的问题。

基本上, System.currentTimeMillis()只是读取由Windows维护的全局variables(这是它的粒度低),而System.nanoTime()实际上必须执行IO操作。

你正在测量在Windows上,不是。 我在2008年完成了这个练习。nanoTime在Windows上比currentTimeMillis慢。 我记得,在Linux上,nanotime比currentTimeMillis快,而且肯定比在Windows上要快。

重要的是要注意的是,如果您正在尝试测量多个亚毫秒操作的聚合,则必须使用nanopime,就好像在小于1/1000秒的代码中完成操作,比较currentTimeMillis将显示操作为瞬时所以这1000个仍然是瞬间的。 你可能想要做的是使用nanotime,然后四舍五入到最接近的毫秒,所以如果一个操作花了8000纳秒,它将被计为1毫秒,而不是0。

你可能想要做的是使用nanotime,然后四舍五入到最接近的毫秒,所以如果一个操作花了8000纳秒,它将被计为1毫秒,而不是0。

算术注释:

8000纳秒是8微秒是0.008毫秒。 四舍五入将会把它变成0毫秒。