Java 提供了两种获取当前时间的方法:System.nanoTime()
和System.currentTimeMillis()
. 第一个以纳秒为单位给出结果,但实际精度比这差得多(很多微秒)。
JVM 是否已经为每台特定机器提供了可能的最佳价值?否则,是否有一些 Java 库可以提供更精细的测量,可能通过绑定到特定系统?
Java 提供了两种获取当前时间的方法:System.nanoTime()
和System.currentTimeMillis()
. 第一个以纳秒为单位给出结果,但实际精度比这差得多(很多微秒)。
JVM 是否已经为每台特定机器提供了可能的最佳价值?否则,是否有一些 Java 库可以提供更精细的测量,可能通过绑定到特定系统?
获得超精确时间测量的问题是某些处理器不能/不提供如此微小的增量。
据我所知,System.currentTimeMillis()
这System.nanoTime()
是你能找到的最好的测量方法。
请注意,两者都返回一个long
值。
在 Java 中将时间测量到纳秒级有点毫无意义;偶尔的 GC 命中将很容易消除这可能提供的任何准确性。无论如何,文档指出,虽然它提供纳秒精度,但它与纳秒精度不同。并且有些操作系统在任何情况下都不报告纳秒(这就是为什么您在访问它们时会发现量化为 1000 的答案;这不是运气,而是限制)。
不仅如此,而且根据操作系统实际实现该功能的方式,您可能会发现量化结果无论如何都会出现(例如,答案总是以 64 或 128 结尾,而不是中间值)。
还值得注意的是,该方法的目的是找到某个(附近)开始时间与现在之间的两个时间差;如果您在长时间运行的应用程序开始时使用 System.nanoTime(),然后在很长一段时间后使用 System.nanoTime(),它可能与实时相差甚远。所以你应该只在不到 1 秒的时间内真正使用它;如果您需要更长的运行时间,那么毫秒就足够了。(如果不是,那就补上最后几个数字;你可能会给客户留下深刻印象,结果也同样有效。)
不幸的是,我认为目前 java RTS 还不够成熟。
Java 时间确实尝试提供最佳价值(它们实际上委托本机代码调用获取内核时间)。但是,JVM 规范主要针对 GC 活动和对底层系统的支持等内容做出这种粗略的时间测量免责声明。
除非您的应用不需要执行 GC,否则我还没有弄清楚如何解决 #1。一个体面的中等大小的应用程序可能偶尔会在 GC 暂停上花费数十毫秒。如果您的精度要求低于 10 毫秒,您可能不走运。
至于 #2,您可以调整 linux 内核以提供更高的精度。但是,由于现在内核上下文切换更加频繁,因此您的开箱即用也越来越少。
或许,我们应该换个角度来看。OPS需要10ms以下的精度有什么原因吗?是否可以告诉 Ops 精度为 10 毫秒并且当时还查看 GC 日志,所以他们知道在没有 GC 活动的情况下时间是 +-10 毫秒准确?
JNI:创建一个简单的函数来访问 Intel RDTSC 指令或 ARM 中协处理器 p15 的 PMCCNTR 寄存器。
纯 Java:如果您愿意延迟到时钟滴答声,您可能会获得更好的价值。您可以旋转检查 System.nanoTime() 直到值更改。例如,如果您知道 System.nanoTime() 的值在您的平台上每 10000 次循环迭代就会发生变化量 DELTA,那么实际事件时间是 finalNanoTime-DELTA*ITERATIONS/10000。在进行实际测量之前,您需要“预热”代码。
Hack(仅用于分析等):如果垃圾收集让您失望,您始终可以使用在不创建对象的第二个 jvm 中运行的高优先级线程来测量时间。让它在你用作时钟的共享内存中自旋递增一个 long。