简体   繁体   English

Java中的精确时间测量

[英]Precise time measurement in Java

Java gives access to two method to get the current time: System.nanoTime() and System.currentTimeMillis() . Java提供了两种获取当前时间的方法: System.nanoTime()System.currentTimeMillis() The first one gives a result in nanoseconds, but the actual accuracy is much worse than that (many microseconds). 第一个给出一个纳秒的结果,但实际精度比那个(很多微秒)差很多。

Is the JVM already providing the best possible value for each particular machine? JVM是否已为每台特定机器提供最佳价值? Otherwise, is there some Java library that can give finer measurement, possibly by being tied to a particular system? 否则,是否有一些Java库可以通过绑定到特定系统来提供更精细的测量?

The problem with getting super precise time measurements is that some processors can't/don't provide such tiny increments. 获得超精确时间测量的问题在于某些处理器不能/不能提供如此微小的增量。

As far as I know, System.currentTimeMillis() and System.nanoTime() is the best measurement you will be able to find. 据我所知, System.currentTimeMillis()System.nanoTime()是您能够找到的最佳度量。

Note that both return a long value. 请注意,两者都返回一个long值。

It's a bit pointless in Java measuring time down to the nanosecond scale; 在Java测量时间到纳秒级别时,这有点毫无意义; an occasional GC hit will easily wipe out any kind of accuracy this may have given. 偶尔的GC命中将很容易消除这可能给出的任何准确性。 In any case, the documentation states that whilst it gives nanosecond precision, it's not the same thing as nanosecond accuracy; 在任何情况下,文档都指出虽然它提供纳秒精度,但它与纳秒精度不同; and there are operating systems which don't report nanoseconds in any case (which is why you'll find answers quantized to 1000 when accessing them; it's not luck, it's limitation). 并且有些操作系统在任何情况下都不报告纳秒(这就是为什么你在访问时会发现量化为1000的答案;这不是运气,而是限制)。

Not only that, but depending on how the feature is actually implemented by the OS, you might find quantized results coming through anyway (eg answers that always end in 64 or 128 instead of intermediate values). 不仅如此,而且取决于操作系统实际实现的功能,您可能会发现无论如何都会出现量化结果(例如总是以64或128而不是中间值结束的答案)。

It's also worth noting that the purpose of the method is to find the two time differences between some (nearby) start time and now; 值得注意的是,该方法的目的是找到一些(附近)开始时间和现在之间的两个时间差; if you take System.nanoTime() at the start of a long-running application and then take System.nanoTime() a long time later, it may have drifted quite far from real time. 如果你在长时间运行的应用程序的开头采用System.nanoTime(),然后很长一段时间后采用System.nanoTime(),它可能已经远离实时。 So you should only really use it for periods of less than 1s; 所以你应该只在不到1秒的时间内使用它; if you need a longer running time than that, milliseconds should be enough. 如果你需要比这更长的运行时间,毫秒就足够了。 (And if it's not, then make up the last few numbers; you'll probably impress clients and the result will be just as valid.) (如果不是,那么补上最后几个数字;你可能会给客户留下深刻印象,结果也同样有效。)

Unfortunately, I don't think java RTS is mature enough at this moment. 不幸的是,我认为java RTS目前还不够成熟。

Java time does try to provide best value (they actually delegate the native code to call get the kernal time). Java时间确实试图提供最佳价值(他们实际上委托本地代码调用获取内核时间)。 However, JVM specs make this coarse time measurement disclaimer mainly for things like GC activities, and support of underlying system. 但是,JVM规范使得这种粗略的时间测量免责声明主要用于GC活动和底层系统的支持。

  • Certain GC activities will block all threads even if you are running concurrent GC. 即使您正在运行并发GC,某些GC活动也将阻止所有线程。
  • default linux clock tick precision is only 10ms. 默认的linux时钟刻度精度仅为10ms。 Java cannot make it any better if linux kernal does not support. 如果linux kernal不支持,Java无法做得更好。

I haven't figured out how to address #1 unless your app does not need to do GC. 除非你的应用不需要做GC,否则我还没弄清楚如何解决#1问题。 A decent and med size application probably and occasionally spends like tens of milliseconds on GC pauses. 一个体面和中等大小的应用程序可能偶尔花费几十毫秒的GC停顿时间。 You are probably out of luck if your precision requirement is lower 10ms. 如果你的精度要求低10ms,你可能会运气不好。

As for #2, You can tune the linux kernal to give more precision. 对于#2,你可以调整linux内核以提供更高的精度。 However, you are also getting less out of your box because now kernal context switch more often. 但是,由于现在更频繁地切换内核上下文,因此您也可以减少开箱即用。

Perhaps, we should look at it different angle. 也许,我们应该从不同的角度来看待它。 Is there a reason that OPS needs precision of 10ms of lower? 有没有理由说OPS需要10ms以下的精度? Is it okay to tell Ops that precision is at 10ms AND also look at the GC log at that time, so they know the time is +-10ms accurate without GC activity around that time? 是否可以告诉Ops精度为10ms并且还查看当时的GC日志,因此他们知道在没有GC活动的情况下,时间是+ 1-10ms准确吗?

If you are looking to record some type of phenomenon on the order of nanoseconds, what you really need is a real-time operating system . 如果您希望记录某种类型的纳秒级现象,您真正需要的是实时操作系统 The accuracy of the timer will greatly depend on the operating system's implementation of its high resolution timer and the underlying hardware. 定时器的准确性将在很大程度上取决于操作系统的高分辨率计时器和底层硬件的实现。

However, you can still stay with Java since there are RTOS versions available. 但是,由于有可用的RTOS版本,您仍然可以继续使用Java。

JNI: Create a simple function to access the Intel RDTSC instruction or the PMCCNTR register of co-processor p15 in ARM. JNI:创建一个简单的函数来访问ARM中的Intel RDTSC指令或协处理器p15的PMCCNTR寄存器。

Pure Java: You can possibly get better values if you are willing to delay until a clock tick. 纯Java:如果你愿意延迟到时钟滴答,你可能会得到更好的价值。 You can spin checking System.nanoTime() until the value changes. 您可以旋转检查System.nanoTime()直到值更改。 If you know for instance that the value of System.nanoTime() changes every 10000 loop iterations on your platform by amount DELTA then the actual event time was finalNanoTime-DELTA*ITERATIONS/10000. 例如,如果您知道System.nanoTime()的值在您的平台上按DELTA更改每10000次循环迭代,则实际事件时间为finalNanoTime-DELTA * ITERATIONS / 10000。 You will need to "warm-up" the code before taking actual measurements. 在进行实际测量之前,您需要“预热”代码。

Hack (for profiling, etc, only): If garbage collection is throwing you off you could always measure the time using a high-priority thread running in a second jvm which doesn't create objects. Hack(仅用于分析等):如果垃圾收集让你失望,你总是可以使用在第二个jvm中运行但不创建对象的高优先级线程来测量时间。 Have it spin incrementing a long in shared memory which you use as a clock. 让它在用作时钟的共享内存中旋转增量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM