Proposal: standardize time-based effects on performance.now()

208 views
Skip to first unread message

Luke Westby

unread,
Aug 21, 2016, 5:28:55 PM8/21/16
to elm-dev
Hi folks!

I was reviewing some older elm-dev threads today when I revisited the following:
https://groups.google.com/forum/m/#!topic/elm-dev/n9Kv9WDMo4E

I got to playing with performance.now() some more and realized that there is actually a notable difference between the normalized result it gives and the one from Date.now() that can range from 10ms to almost half a second depending on the number of calls that have already been made to either function. It seems this stems from performance.now() reading from a separate clock than Date.now().

The immediate issue is that elm-lang/animation-frame, which uses high-res timestamps, is supposed to be designed so that timestamps are correct when used against Time.now, but like I said, they will be off be at least a small number of milliseconds.

This can be fixed by standardizing on one source of timestamps for all time-based effects. I'd like to propose that source be performance.now() when available with a fallback to Date.now(). This could be made simple to manage in code by writing a currentTime() function in Native.Time that abstracts that decision in a consistent way for all other packages.

The benefit to doing this is that Elm can guarantee that all timestamps are the most precise that the platform can offer. This could make Time.now a sufficient tool for building benchmarking packages and tools entirely in Elm so that they can be published on the package registry.

I'm happy to write these changes and submit a PR, as always.

To sumarrize,
Do:
- Add a function to Native.Time to get current time from performance.now() and fall back to Date.now()
- Use it wherever timestamps are needed in elm-lang/* packages

Get:
- A bug in animation-frame gets fixed
- People can start experimenting with benchmarking tools in pure Elm

Evan Czaplicki

unread,
Aug 22, 2016, 1:41:31 PM8/22/16
to elm-dev
Sounds great to me!

Go for it and let me know if you need any reviews or anything. It may be necessary to do some grep'ing through @elm-lang platform packages that may be using this behind the scenes.


--
You received this message because you are subscribed to the Google Groups "elm-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-dev+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elm-dev/9703a362-9d10-4178-a344-8a51e53d9061%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Luke Westby

unread,
Aug 23, 2016, 10:15:00 AM8/23/16
to elm-dev
Sounds good! Looks like animation-frame is the only other package that uses Date.now() natively.

I am observing some interesting behavior with performance.now() which may be prohibitive for moving forward that I'd love help from others in verifying. I'm observing that in Chrome when a browser tab has been left open for a long time and the computer is allowed to sleep and then everything it resumes the browser stops running the clock used by performance.now() while the browsing context is paused. So if long-running applications are expecting to be able to stay open and running in a user's browser for a long time and use a timer this would result in major problems. Can anyone else help me verify this? The symptom can be demonstrated by following the previously mentioned steps to get Chrome to create a browsing context and then pause it, and then you can run console.log(Date.now() - performance.timing.navigationStart - performance.now()) and the difference should be fairly large.


To unsubscribe from this group and stop receiving emails from it, send an email to elm-dev+u...@googlegroups.com.

Luke Westby

unread,
Aug 23, 2016, 10:20:56 AM8/23/16
to elm-dev
Another possibility is that this is just steady drift between the two clocks that only becomes really noticeable after a longer period of time has passed.

Luke Westby

unread,
Aug 23, 2016, 1:20:19 PM8/23/16
to elm-dev
So thanks to some help from friends at Mozilla, we found out that performance.now() is only meant to be used for measuring and isn't intended to be accurate as a general timer.


New plan is: I'm going to submit a PR to have animation-frame always use Date.now() because that issue is still present, and then I'll come up with a new proposal for adding a primitive to help people benchmark Elm code in Elm and that can be a whole separate conversation.

Evan Czaplicki

unread,
Aug 23, 2016, 1:35:16 PM8/23/16
to elm-dev
Interesting result! It's weird that it's hard to just get a better timer. I don't fully get it.

In any case, this plan makes sense to me!

To unsubscribe from this group and stop receiving emails from it, send an email to elm-dev+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elm-dev/a6fb9968-4163-4711-b0f1-ea8bf2912446%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages