Java中的精确时间测量

时间:2009-09-30 22:06:43

标签: java performance measurement

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

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

5 个答案:

答案 0 :(得分:15)

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

据我所知,System.currentTimeMillis()System.nanoTime()是您能找到的最佳衡量标准。

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

答案 1 :(得分:5)

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

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

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

答案 2 :(得分:1)

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

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

  • 即使您正在运行并发GC,某些GC活动也会阻止所有线程。
  • 默认的linux时钟刻度精度仅为10ms。如果linux kernal不支持,Java无法做得更好。

除非你的应用不需要做GC,否则我还没弄清楚如何解决#1问题。一个体面和中等大小的应用程序可能偶尔花费几十毫秒的GC停顿时间。如果你的精度要求低于10毫秒,你可能会运气不好。

至于#2,你可以tune the linux kernal提供更高的精确度。但是,由于现在内核上下文更频繁地切换,所以你的盒子也越来越少了。

也许,我们应该从不同的角度来看待它。有没有理由说OPS需要10ms以下的精度?是否可以告诉Ops精度为10ms并且还查看当时的GC日志,因此他们知道在没有GC活动的情况下,时间是+ 1-10ms准确吗?

答案 3 :(得分:0)

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

但是,由于可以使用RTOS版本,因此您仍然可以继续使用Java。

答案 4 :(得分:0)

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

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

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