17

Java 提供了两种获取当前时间的方法:System.nanoTime()System.currentTimeMillis(). 第一个以纳秒为单位给出结果,但实际精度比这差得多(很多微秒)。

JVM 是否已经为每台特定机器提供了可能的最佳价值?否则,是否有一些 Java 库可以提供更精细的测量,可能通过绑定到特定系统?

4

5 回答 5

19

获得超精确时间测量的问题是某些处理器不能/不提供如此微小的增量。

据我所知,System.currentTimeMillis()System.nanoTime()是你能找到的最好的测量方法。

请注意,两者都返回一个long值。

于 2009-09-30T22:19:48.370 回答
6

在 Java 中将时间测量到纳秒级有点毫无意义;偶尔的 GC 命中将很容易消除这可能提供的任何准确性。无论如何,文档指出,虽然它提供纳秒精度,但它与纳秒精度不同。并且有些操作系统在任何情况下都不报告纳秒(这就是为什么您在访问它们时会发现量化为 1000 的答案;这不是运气,而是限制)。

不仅如此,而且根据操作系统实际实现该功能的方式,您可能会发现量化结果无论如何都会出现(例如,答案总是以 64 或 128 结尾,而不是中间值)。

还值得注意的是,该方法的目的是找到某个(附近)开始时间与现在之间的两个时间差;如果您在长时间运行的应用程序开始时使用 System.nanoTime(),然后在很长一段时间后使用 System.nanoTime(),它可能与实时相差甚远。所以你应该只在不到 1 秒的时间内真正使用它;如果您需要更长的运行时间,那么毫秒就足够了。(如果不是,那就补上最后几个数字;你可能会给客户留下深刻印象,结果也同样有效。)

于 2009-09-30T22:38:45.297 回答
1

不幸的是,我认为目前 java RTS 还不够成熟。

Java 时间确实尝试提供最佳价值(它们实际上委托本机代码调用获取内核时间)。但是,JVM 规范主要针对 GC 活动和对底层系统的支持等内容做出这种粗略的时间测量免责声明。

  • 即使您正在运行并发 GC,某些 GC 活动也会阻塞所有线程。
  • 默认 linux 时钟滴答精度仅为 10 毫秒。如果 linux 内核不支持,Java 不能让它变得更好。

除非您的应用不需要执行 GC,否则我还没有弄清楚如何解决 #1。一个体面的中等大小的应用程序可能偶尔会在 GC 暂停上花费数十毫秒。如果您的精度要求低于 10 毫秒,您可能不走运。

至于 #2,您可以调整 linux 内核以提供更高的精度。但是,由于现在内核上下文切换更加频繁,因此您的开箱即用也越来越少。

或许,我们应该换个角度来看。OPS需要10ms以下的精度有什么原因吗?是否可以告诉 Ops 精度为 10 毫秒并且当时还查看 GC 日志,所以他们知道在没有 GC 活动的情况下时间是 +-10 毫秒准确?

于 2009-09-30T22:38:22.677 回答
0

如果您希望以纳秒级记录某种类型的现象,那么您真正需要的是实时操作系统。计时器的准确性将在很大程度上取决于操作系统对其高分辨率计时器和底层硬件的实现。

但是,您仍然可以继续使用 Java,因为有可用的 RTOS 版本。

于 2009-09-30T22:39:38.180 回答
0

JNI:创建一个简单的函数来访问 Intel RDTSC 指令或 ARM 中协处理器 p15 的 PMCCNTR 寄存器。

纯 Java:如果您愿意延迟到时钟滴答声,您可能会获得更好的价值。您可以旋转检查 System.nanoTime() 直到值更改。例如,如果您知道 System.nanoTime() 的值在您的平台上每 10000 次循环迭代就会发生变化量 DELTA,那么实际事件时间是 finalNanoTime-DELTA*ITERATIONS/10000。在进行实际测量之前,您需要“预热”代码。

Hack(仅用于分析等):如果垃圾收集让您失望,您始终可以使用在不创建对象的第二个 jvm 中运行的高优先级线程来测量时间。让它在你用作时钟的共享内存中自旋递增一个 long。

于 2017-01-25T00:47:00.787 回答