kotlin icon indicating copy to clipboard operation
kotlin copied to clipboard

Switch to use System.nanoTime in measureTimeMillis

Open ansman opened this issue 1 year ago • 10 comments

Previously measureTimeMillis used System.currentTimeMillis which is not ideal for several reasons. Firstly it often has a resolution of 10s of milliseconds and secondly because it can be adjusted by something like an NTP update so the returned value could be negative.

Instead it now delegates to measureNanoTime which uses System.nanoTime which has the highest resolution the system provides as well as being guaranteed to be monotonically increasing.

This fixes KT-52686 and KT-24431

ansman avatar Sep 13 '22 12:09 ansman

I would argue that on Android we still want to use nanoTime over elapsedRealtime as it's more likely that the caller does not want to include time spent in sleep.

ansman avatar Sep 13 '22 12:09 ansman

There is probably related pull request: https://github.com/JetBrains/kotlin/pull/1964

KvanTTT avatar Sep 13 '22 18:09 KvanTTT

Yeah definitely. But holy moly, open for 4 years?!

That PR seems dead. I've incorporated the changes from the discussion.

ansman avatar Sep 13 '22 20:09 ansman

You also tried before lol #2077. Hopefully this time it lands!

JakeWharton avatar Sep 13 '22 20:09 JakeWharton

Damn, I've come full circle it seems.

ansman avatar Sep 13 '22 20:09 ansman

cc @ilya-g

abelkov avatar Sep 14 '22 06:09 abelkov

Hi folks and sorry for our (missing) PR handling policy!

We've discussed it internally and would like to discuss an alternative proposal.

We do acknowledge the need of measureTimeMillis and that this is the appropriate time unit for most cases. We also acknowledge that in its current state, the API is really dangerous to use -- it's unlikely that an average user expects this method to return a negative number (or even zero), which may lead to potential crashes and unspecified behaviour, not talking about its resolution issue.

Apart from that, we have an adjacent inconsistently-named API: measureNanoTime (named respectively for its underlying source, System.nanoTime()), which looks off when compared with measureTime or measureTimeMillis.

The preliminary idea is the following:

  • Stabilize measureTime
  • Soft-deprecate* of measureTimeMillis and measureNanoTime to nudge people towards measureTime {} or measureTime {}.inWholeMilliseconds (the latter is required only if the programmatic use of long is required)

In that way, we do avoid potentially breaking changes, get rid of APIs we do not like, and encourage people to use the corresponding Duration type (long for time units is well-known to be error-prone).

The downsides are also clear:

  • We preserve the status quo, and it's not really helpful for current users (arguably we save a breaking change here, though the impact is likely to be negligible)
  • We [soft-]deprecate common API, forcing users to make an extra effort
  • We potentially make the previously concise pattern more verbose (.inWholeMilliseconds), at least for the initial migration phase.

What do you think about that?

  • On a side note, it seems like the language itself needs a mechanism for "soft-deprecation" -- not a "this is a warning and bad API, you should migrate from it now", but rather a nudge "here is a better alternative that we kindly suggest with IDE assistance"

qwwdfsad avatar Sep 15 '22 16:09 qwwdfsad

On a side note, it seems like the language itself needs a mechanism for "soft-deprecation"

Maybe DeprecationLevel.NOTE? Or INFORMATIVE?

JakeWharton avatar Sep 15 '22 16:09 JakeWharton

Maybe DeprecationLevel.NOTE? Or INFORMATIVE?

Love the suggestion. I'll try to write a proper YT proposal (aka pre-KEEP) around next week and will definitely use these as viable options

qwwdfsad avatar Sep 15 '22 18:09 qwwdfsad

That seems like a good solution and I have already been using measureTime since it was added. But regardless I still think this PR should land as it is a strictly good improvement.

ansman avatar Sep 16 '22 14:09 ansman