处理时间措施的最佳方法是什么? [英] Best approach for dealing with time measures?

查看:215
本文介绍了处理时间措施的最佳方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标是编写一个测量方法执行或交易时间以及处理测量的框架,即存储,分析等。事务可能包括调用外部系统,同步或异步等待结果。

My goal is to write a framework for measuring method execution or transaction time and for processing the measurements, i.e. storing, analysis etc. Transaction may include calls to external systems, with synchronously or asynchronously waiting for the results.

围绕该主题已经存在一些问题,例如

There already have been some questions around that topic, like

  • "How do I time a method's execution"
  • "Measure execution time for a Java method"
  • "System.currentTimeMillis vs System.nanoTime"

所有答案归结为三种方法来花时间

And all the answers boil down to three approaches for taking the time


  • System.currentTim eMillis()

  • System.nanoTime()

  • Instant.now()持续时间(自Java 8开始)

  • System.currentTimeMillis()
  • System.nanoTime()
  • Instant.now() and Duration(since Java 8)

我知道,所有这些都有一些影响

I know, all of these have some implications

此方法的结果取决于平台。在Linux上你获得1ms的分辨率,在Windows中你得到10ms(单核)~15ms(多核)。所以可以测量大型运行操作或短期运行操作的多次执行。

The result of this method depends on the platform. On Linux you get 1ms resolution, of Windows you get 10ms (single core) ~15ms (multi core). So it's ok for measuring large running operations or multiple executions of short running ops.

你得到一个高分辨率的时间测量,具有纳秒精度(但不一定是纳秒精度),并且在292年后你会溢出(我可以忍受)。

You get a high resolution time measure, with nano second precision (but not necessarily nano second accuracy) and you get an overflow after 292 years (I could live with that).

从Java 8开始,有新的时间API。瞬间有第二个和纳秒的字段,因此它在Object引用的顶部使用两个长值(对于 Duration ,相同)。您还可以获得纳秒级精度,具体取决于基础时钟(请参阅 Java 8 Instant .now()具有纳秒分辨率?)。实例化是通过调用 Instant.now()来完成的,它向普通系统映射到 System.currentTimeMillis()时间。

Since Java 8 there is the new time API. An instant has a second and a nano second field, so it uses on top of the Object reference two long values (same for Duration). You also get nano second precision, depending on the underlying clock (see "Java 8 Instant.now() with nanosecond resolution?"). The instantiaion is done by invoking Instant.now() which maps down to System.currentTimeMillis() for the normal System clock.

根据事实,很明显,只有 System.nanoTime()才能达到最佳精度。 ,但我的问题更多地针对最佳实践来处理一般的措施,这不仅包括措施,还包括措施处理。

Given the facts, it becomes apparent, that best precision is only achievable with System.nanoTime(), but my question targets more towards a best-practice for dealing with the measures in general, which not only includes the measure taking but also the measure handling.


  • Instant和Duration提供最佳API支持(计算,比较等),但在标准情况下具有os-dependend精度,内存和创建度量的开销更大(对象构造) ,更深层的callstack)

  • Instant and Duration provide best API support (calculating, comparing, etc) but have os-dependend precision in standard case, and more overhead for memory and creating a measure (Object construction, deeper callstack)

System.nanoTime()和System.currentTimeMillis()具有不同的精度级别,但只有基本的api支持(数学操作on ()但是要保持记忆力的速度越来越快。

System.nanoTime() and System.currentTimeMillis() have different levels of precision but only have basic "api" support (math operations on long), but are faster to get and smaller to keep in memory.

那么最好的方法是什么?有没有我没想过的含义?有没有其他选择?

So what would be the best approach? Are there any implications I didn't think of? Are there any alternatives?

推荐答案

你过分关注精度的不重要细节。如果要测量/分析某些操作的执行,则必须确保这些操作运行的时间足够长,以使测量不受一次性工件,线程调度时间,垃圾收集或HotSpot优化的微小差异的影响。在大多数情况下,如果差异小于毫秒级,则从它们得出结论是没有用的。

You are focusing too much on the unimportant detail of the precision. If you want to measure/profile the execution of certain operations, you have to make sure that these operation run long enough to make the measurement unaffected by one-time artifacts, small differences in thread scheduling timing, garbage collection or HotSpot optimization. In most cases, if the differences become smaller than the millisecond scale, they are not useful to draw conclusions from them.

更重要的方面是这些工具是否是为你的任务。 System.currentTimeMillis()以及所有其他基于挂钟的API,无论它们是否基于 currentTimeMillis() ,旨在为您提供一个时钟,旨在与地球的旋转及其绕太阳的路径同步,加载它的负担 Leap Seconds 和其他纠正措施,更不用说计算机的时钟可能与挂钟不同并且得到纠正,例如通过NTP更新,在最糟糕的情况下,当你试图测量你的经过时间时,可能甚至倒退。

The more important aspect is whether the tools are designed for your task. System.currentTimeMillis() and all other wall-clock based APIs, whether they are based on currentTimeMillis() or not, are designed to give you a clock which is intended to be synchronized with Earth’s rotation and its path around the Sun, which loads it with the burden of Leap Seconds and other correction measures, not to speak of the fact that your computer’s clock may be out of sync with the wall clock anyway and get corrected, e.g. via NTP updates, in the worst case jumping right when you are trying to measure your elapsed time, perhaps even backwards.

相比之下, System.nanoTime() 旨在衡量已用时间(正是您想要做的)而不是其他任何内容。由于其返回值具有未指定的原点,甚至可能是负数,因此此方法返回的两个值之间只有差异才有意义。您甚至可以在文档中找到它:

In contrast, System.nanoTime() is designed to measure elapsed time (exactly what you want to do) and nothing else. Since its return value has an unspecified origin and may even be negative, only differences between two values returned by this method make any sense at all. You will find this even in the documentation:


此方法返回的值仅在两个此类值之间的差异时才有意义计算Java虚拟机的相同实例。

The values returned by this method become meaningful only when the difference between two such values, obtained within the same instance of a Java virtual machine, is computed.

因此,当您想要测量和处理方法执行所用的时间时或交易, System.nanoTime()是要走的路。当然,它只提供一个裸 long 值,但不清楚你想要什么样的API支持。由于时间点不相关甚至分散注意力,你只会有一个持续时间,你可以转换为其他时间单位或者,如果你想使用新的时间API,你可以创建一个持续时间使用 Duration.ofNanos(long) ,允许您添加和减去持续时间值并进行比较,但您可以做的更多。你一定不能将它们与基于挂钟或日历的持续时间混合起来......

So when you want to measure and process the elapsed time of your method execution or transactions, System.nanoTime() is the way to go. Granted, it only provides a naked long value, but it isn’t clear what kind of API support you want. Since points of time are irrelevant and even distracting here, you’ll have a duration only, which you may convert to other time units or, if you want to use the new time API, you can create a Duration object using Duration.ofNanos(long), allowing you to add and subtract duration values and compare them, but there isn’t much more you could do. You must not mix them up with wall-clock or calendar based durations…

作为最后一点,文档有点不精确局限性。如果计算 System.nanoTime()返回的两个值之间的差异,则数值溢出本身并不错。由于计数器具有未指定的原点,因此操作的起始值可能接近 Long.MAX_VALUE ,而结束值接近 Long.MIN_VALUE 因为JVM的计数器有溢出。在这种情况下,计算差异将导致另一次溢出,从而产生差异的正确值。但是,如果您将这个差异存储在签名的 long 中,它最多可以保持2⁶3纳秒,将差异限制为最多292年,但是如果将其视为 unsigned长,例如通过 Long.compareUnsigned Long.toUnsignedString ,你可以处理甚至2⁶⁴纳秒的持续时间,换句话说你可以测量长达584年的经过时间这样,如果你的电脑没有中断......

As a final note, the documentation is a bit imprecise about the limitation. If you are calculating the difference between two values returned by System.nanoTime(), a numerical overflow isn’t bad per se. Since the counter has an unspecified origin, the start value of your operation might be close to Long.MAX_VALUE whereas the end value is close to Long.MIN_VALUE because the JVM’s counter had an overflow. In this case, calculating the difference will cause another overflow, producing a correct value for the difference. But if you store that difference in a signed long, it can hold at most 2⁶³ nanoseconds, limiting the difference to max 292 years, but if you treat it as unsigned long, e.g. via Long.compareUnsigned and Long.toUnsignedString, you may handle even 2⁶⁴ nanoseconds duration, in other words you can measure up to 584 years of elapsed time this way, if your computer doesn’t break in-between…

这篇关于处理时间措施的最佳方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆