Java中精确的时间测量

发布于 2024-08-06 02:39:01 字数 207 浏览 8 评论 0原文

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

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

Java gives access to two method to get the current time: System.nanoTime() and 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?
Otherwise, is there some Java library that can give finer measurement, possibly by being tied to a particular system?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

晒暮凉 2024-08-13 02:39:01

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

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

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

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.

Note that both return a long value.

哭了丶谁疼 2024-08-13 02:39:01

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

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

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

It's a bit pointless in Java measuring time down to the nanosecond scale; an occasional GC hit will easily wipe out any kind of accuracy this may have given. 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).

Not only that, but depending on how the feature is actually implemented by the OS, you might find quantized results coming through anyway (e.g. answers that always end in 64 or 128 instead of intermediate values).

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. So you should only really use it for periods of less than 1s; 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.)

对你再特殊 2024-08-13 02:39:01

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

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

  • 即使您正在运行并发 GC,某些 GC 活动也会阻塞所有线程。
  • 默认的linux时钟节拍精度仅为10ms。如果Linux内核不支持,Java就无法使它变得更好。

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

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

或许,我们应该换个角度来看待它。 OPS 需要 10ms 或更低的精度是否有原因?是否可以告诉运维人员精度为 10 毫秒,并查看当时的 GC 日志,以便他们知道在该时间附近没有 GC 活动的情况下时间是 +-10 毫秒准确?

Unfortunately, I don't think java RTS is mature enough at this moment.

Java time does try to provide best value (they actually delegate the native code to call get the kernal time). However, JVM specs make this coarse time measurement disclaimer mainly for things like GC activities, and support of underlying system.

  • Certain GC activities will block all threads even if you are running concurrent GC.
  • default linux clock tick precision is only 10ms. Java cannot make it any better if linux kernal does not support.

I haven't figured out how to address #1 unless your app does not need to do GC. A decent and med size application probably and occasionally spends like tens of milliseconds on GC pauses. You are probably out of luck if your precision requirement is lower 10ms.

As for #2, You can tune the linux kernal to give more precision. 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? 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?

北斗星光 2024-08-13 02:39:01

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

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

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.

有深☉意 2024-08-13 02:39:01

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

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

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

JNI:
Create a simple function to access the Intel RDTSC instruction or the PMCCNTR register of co-processor p15 in ARM.

Pure Java:
You can possibly get better values if you are willing to delay until a clock tick. You can spin checking System.nanoTime() until the value changes. 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. 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. Have it spin incrementing a long in shared memory which you use as a clock.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文