2009-09-30 168 views
14

的Java可以访问两个方法来获取当前时间:System.nanoTime()System.currentTimeMillis()。第一个以纳秒为单位给出结果,但实际的精度比那个要差很多(几微秒)。精确的时间度量在Java中

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

+0

在什么操作系统中,您是否证明System.nanoTime()产生的输出已被“许多微秒”关闭? – 2009-09-30 22:20:41

+0

这是在一个双核心机器上的Linux系统,但它是一个相当老的安装(从2007年初...)。也许这是原因。我会检查一些更近的​​事情。另外从我记得,我有连续的电话返回相同的价值,然后跳几个micaresconds。 – penpen 2009-09-30 22:35:16

回答

13

与获得超精密时间测量的问题是,有些处理器不能/不会提供这种微小的增量。

据我所知,System.currentTimeMillis()System.nanoTime()是您能够找到的最佳测量值。

注意,这两个返回long值。

+0

现代处理器(> 1ghz)的循环速度快于1纳秒,因此它们在技术上相当有能力。 – 2009-09-30 22:29:10

+2

他们可以跟踪时间,但这并不意味着他们准确地报告时间。 – jjnguy 2009-09-30 22:30:41

+2

不要忘记,有开销: 有一个系统调用,通常本身是微秒级(只是跳到内核和退出,但这是昂贵的时间读取部分)。 然后,您可能会启用预占权加载系统,这意味着可能会安排其他某个进程。即使情况并非如此,这意味着您仍然需要跳入JVM中,即使使用JIT代码也会产生轻微的开销。 在原生gode中,您可以使用clock_gettime&friends API来探索高分辨率计时器的准确性。 – Vitali 2009-09-30 22:54:51

1

不幸的是,我不认为Java RTS在这一刻已经够成熟了。

Java的时间并尽量提供最好的价值(他们实际上委托本地代码调用获取籽粒时间)。但是,JVM规范使得这种粗略的时间测量免责主要针对GC活动以及底层系统的支持。

  • 即使您正在运行并发GC,某些GC活动也会阻塞所有线程。
  • 默认的linux时钟刻度精度只有10ms。如果linux kernal不支持,Java不能让它变得更好。

我还没有想出如何解决#1,除非你的应用程序不需要做GC。一个体面和中等规模的应用程序可能偶尔花费几十毫秒的GC暂停。如果您的精度要求低于10毫秒,那么您可能运气不好。

至于#2,您可以tune the linux kernal给予更高的精度。但是,由于现在更频繁地切换内核上下文,因此您的盒子也越来越少。也许,我们应该从不同的角度来看待它。 OPS需要精度低于10ms的原因吗?可以告诉Ops精确度在10ms,并且当时也查看GC日志,所以他们知道在那段时间没有GC活动时,精确度为+ -10ms?

+0

”某些GC活动将阻止所有线程,即使您正在运行并发GC。“ 你说得对,但另一方面,通过调整JVM参数,可以部分缓解这个问题。正如提议的那样,是的,GC中的时间可以考虑在内,并且被删除。 – penpen 2009-09-30 22:49:47

+0

我的观点并不是我们无法调整它。我的观点是,即使你调整GC,你也无法让GC降低到你似乎喜欢的纳秒级别。那是我对“体面”应用程序的定义,应该已经调整过了:) – 2009-09-30 23:27:09

5

这是Java中的一个位无意义测量时间缩短到纳秒规模;偶尔的GC命中将很容易消除这种可能的准确性。在任何情况下,文档都指出虽然它提供了纳秒精度,但它与纳秒精度不一样;并且有操作系统在任何情况下都不报告纳秒(这就是为什么您在访问时会查找量化到1000的答案;这不是运气,而是限制)。

不仅如此,但根据功能如何实际上是由操作系统来实现,你可能会发现通过反正(例如答案总是在最后64或128,而不是中间值)来量化结果。

这也是值得注意的是,该法的目的是为了找到一些(附近)开始的时间,现在两者之间的时间差;如果你把System.nanoTime()在长期运行的应用程序的启动,然后采取System.nanoTime()很长一段时间后,它可能与实际时间很远漂流。所以你应该只使用它少于1秒的时间;如果你需要比这更长的运行时间,毫秒应该足够了。 (如果不是这样,那么补上最后几个数字;你可能会给客户留下深刻的印象,结果也会一样有效。)

+0

“所以你应该只使用它少于1秒的时间”。这是一个小的重复现象。 “如果不是,那么补上最后几个数字”。不,他们可能想尝试并重现此:) – penpen 2009-09-30 22:57:58

0

如果您正在寻找以纳秒级别记录某种类型的现象,你真正需要的是real-time operating system。定时器的精确度将在很大程度上取决于操作系统的实现high resolution timer和底层硬件。

但是,由于存在RTOS版本,您仍然可以使用Java。

0

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

纯Java: 如果你愿意延迟到时钟滴答,你可以得到更好的值。你可以旋转检查System.nanoTime(),直到值改变。例如,如果您知道System.nanoTime()的值通过DELTA量每更改一次您的平台上的10000次循环,则实际事件时间为finalNanoTime-DELTA * ITERATIONS/10000。在进行实际测量之前,您需要“预热”代码。

黑客(仅适用于性能分析等): 如果垃圾收集将您抛弃,则可以始终使用在第二个jvm中运行的高优先级线程来测量时间,该线程不会创建对象。让它在您用作时钟的共享内存中旋转递增。