Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

time: Ticker unpredictable behaviour #6142

Closed
alexbrainman opened this issue Aug 14, 2013 · 11 comments

Comments

Projects
None yet
5 participants
@alexbrainman
Copy link
Member

commented Aug 14, 2013

This program

package main

import (
    "fmt"
    "time"
)

func main() {
    timer := time.NewTicker(time.Nanosecond).C
    start := time.Now()
    for i := 0; i < 100; i++ {
        <-timer
    }
    fmt.Printf("%v\n", time.Now().Sub(start))
}

prints

- "1.56252s" on my Windows XP;
- "196.2966ms" on my Windows 7;
- "10.114019ms" on my Linux;

Which one is correct?

I would expect it to print something like "100ns". Perhaps I am wrong.

Alex
@adg

This comment has been minimized.

Copy link
Contributor

commented Aug 14, 2013

Comment 1:

The sends on a ticker channel are non-blocking, so it's you're missing a bunch of the
ticks. On most systems I'd imagine a channel send takes longer than a nanosecond.
Increase your timings by a few orders of magnitude and you should see the irregularity
go away.

Status changed to WorkingAsIntended.

@adg

This comment has been minimized.

Copy link
Contributor

commented Aug 14, 2013

Comment 2:

Incidentally, the playground's fake timer gets it right:
http://play.golang.org/p/MVftXdDGhU ;-)
@alexbrainman

This comment has been minimized.

Copy link
Member Author

commented Aug 14, 2013

Comment 3:

adg,
I don't think ticker channel is non-blocking. How do you know that? Is it documented
somewhere?
And, secondly, the doco does not specify that it does not work with "smaller" tickers.
And why shouldn't it?
I think we should reopen the issue.
Alex
@adg

This comment has been minimized.

Copy link
Contributor

commented Aug 14, 2013

Comment 4:

It doesn't explicitly say "non-blocking," but http://golang.org/pkg/time/#Ticker says
"It adjusts the intervals or drops ticks to make up for slow receivers."
Why shouldn't it work with 1ns intervals? Maybe it will when machines are fast enough.
Right now it takes ~17ns to call time.Now() on my machine. I don't see how we can
reasonably expect Ticker to reliably deliver ticks on a 1ns interval.
$ go test -bench=Now -run=XXX time
PASS
BenchmarkNow    100000000           16.6 ns/op
@alexbrainman

This comment has been minimized.

Copy link
Member Author

commented Aug 14, 2013

Comment 5:

> ... http://golang.org/pkg/time/#Ticker says
> 
> "It adjusts the intervals or drops ticks to make up for slow receivers."
Well, it is not doing very good job is it?
> Right now it takes ~17ns to call time.Now() on my machine. I don't see how we can
reasonably expect Ticker to reliably deliver ticks on a 1ns interval.
If I am receiving 1 tick, then sure, there is no choice but wait for what OS will deal
us. But if I am receiving 100 ticks from the Ticker, surely we could return immediately
if Ticker time is up at the start of second (or third or ...) receive.
Alex
@adg

This comment has been minimized.

Copy link
Contributor

commented Aug 14, 2013

Comment 6:

I think you are misunderstanding the purpose of Ticker. You are not guaranteed to
receive a tick for each tick in the interval.
It does seem a bit wonky though: http://play.golang.org/p/emE1kO9fLH
@rsc

This comment has been minimized.

Copy link
Contributor

commented Aug 14, 2013

Comment 7:

It's working as intended. If you miss a tick it skips to the next one. That
one might take a little while to deliver. The difference between what's
sent and when it is received is how long the ticker blocked trying to send
you the tick.
@alexbrainman

This comment has been minimized.

Copy link
Member Author

commented Aug 14, 2013

Comment 8:

rsc,
If "ticks are sent" 1ns each, why I "receive" them 15ms apart? Why should I care that
"blocked trying to send you the tick"?
I can understand it is hard to do for one / two ticks, but why is it hard to implement
for 100?
Alex
@rsc

This comment has been minimized.

Copy link
Contributor

commented Aug 14, 2013

Comment 9:

When you call NewTicker(1ns), every 1ns is an opportunity for the ticker to send a tick.
If you're not ready for that tick (you still haven't received the previous tick), that
tick is skipped.
That's just what it does, and how it's documented.
In general you can reconstruct the missing ticks by looking at the times you are
receiving.
@alexbrainman

This comment has been minimized.

Copy link
Member Author

commented Aug 14, 2013

Comment 10:

I am far from convinced, but lets leave it at that. :-)
Alex
@dvyukov

This comment has been minimized.

Copy link
Member

commented Aug 14, 2013

Comment 11:

windows scheduler timer ticks every 15ms
it's difficult to do something with higher resolution

@rsc rsc added this to the Go1.2 milestone Apr 14, 2015

@rsc rsc removed the go1.2maybe label Apr 14, 2015

@golang golang locked and limited conversation to collaborators Jun 24, 2016

This issue was closed.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.