为啥 System.nanoTime() 比 System.currentTimeMillis() 慢(在性能上)?
Posted
技术标签:
【中文标题】为啥 System.nanoTime() 比 System.currentTimeMillis() 慢(在性能上)?【英文标题】:Why is System.nanoTime() way slower (in performance) than System.currentTimeMillis()?为什么 System.nanoTime() 比 System.currentTimeMillis() 慢(在性能上)? 【发布时间】:2013-10-03 20:13:39 【问题描述】:今天我做了一点快速的基准测试来测试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
【问题讨论】:
Why do System.nanoTime() and System.currentTimeMillis() drift apart so rapidly?的可能重复 这篇文章可能会回答你的问题:***.com/a/5839267/658907nanoTime
比currentTimeMillis
更精确,这可能是原因。
不同意这是一个重复的问题。这是询问执行速度。另一个问题是关于漂移的问题。也许答案是相似的,但问题不是。
不回答你的问题,但即使是“慢”nanoTime
也只需要 34 纳秒 来执行。我没有看到很多用例如此缓慢以至于成为问题。
【参考方案1】:
可能仅适用于 Windows。有关类似问题,请参阅 this answer。
基本上,System.currentTimeMillis()
只是读取一个由 Windows 维护的全局变量(这就是它具有低粒度的原因),而 System.nanoTime()
实际上必须进行 IO 操作。
【讨论】:
【参考方案2】:您可能想要做的是使用纳米时间然后四舍五入到最接近的毫秒,因此如果一个操作花费了 8000 纳秒,它将被计为 1 毫秒,而不是 0。
算术笔记:
8000 纳秒是 8 微秒是 0.008 毫秒。四舍五入将花费 0 毫秒。
【讨论】:
【参考方案3】:来自this Oracle blog:
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()。在大多数系统上,它会给出微秒级的分辨率。但请注意,此调用在某些平台上也可能需要几微秒才能执行。
【讨论】:
不错的答案。还有这个网站:stas-blogspot.blogspot.nl/2012/02/… 有人做了一点研究,还展示了不同操作系统上 System.nanoTime 背后的源代码。【参考方案4】:您是在 Windows 上测量的,不是吗。我在 2008 年完成了这个练习。nanoTime 在 Windows 上比 currentTimeMillis 慢。我记得,在 Linux 上,nanotime 比 currentTimeMillis 快,而且肯定比在 Windows 上快。
需要注意的重要一点是,如果您尝试测量多个亚毫秒操作的聚合,则必须使用 nanotime,就好像操作在不到 1/1000 秒的时间内完成您的代码,比较 currentTimeMillis 将显示操作是瞬时的,因此其中 1,000 个仍然是瞬时的。您可能想要做的是使用 nanotime 然后四舍五入到最接近的毫秒,因此如果一个操作花费了 8000 纳秒,它将被计为 1 毫秒,而不是 0。
【讨论】:
【参考方案5】:大多数操作系统(您没有提到您使用的是哪一个)都有一个内存计数器/时钟,可提供毫秒精度(或接近该精度)。对于纳秒精度,大多数必须读取硬件计数器。与硬件通信比读取内存中的一些值要慢。
【讨论】:
以上是关于为啥 System.nanoTime() 比 System.currentTimeMillis() 慢(在性能上)?的主要内容,如果未能解决你的问题,请参考以下文章
System.nanoTime() 的 Java 时代? [复制]
java的System.currentTimeMillis()和System.nanoTime()
System.nanoTime与System.currentTimeMillis的区别