On Sat, Aug 24, 2013 at 11:16 AM, Dmitry Vyukov wrote: On Sat, Aug 24, 2013 at 9:01 PM, Kyle Lemons wrote: On Sat, Aug 24, 2013 at 3:05 AM, Dmitry Vyukov wrote:
On Sat, Aug 24, 2013 at 5:16 AM, Kyle Lemons wrote:
I agree that monotonic sleeps seem like a reasonable default, but I
think we can do that without potentially breaking attempting to sleep
a particular date+time, because you could (possibly wildly) overshoot
presence of clock steps.
Without time steps both sleeps behave the same way, right?
In the presence of time steps, it's somewhat unclear to me what a user
can potentially want, and what a reasonable behavior of sleeps can be
If we have to choose between the two, I think non-monotonic is marginally
less surprising. Many "sleep" APIs are documented as sleeping for "at
least" the duration specified, though, so strictly speaking we could save
the start time, and keep sleeping for monotonic durations until at least the
specified duration on the system clock has passed. In this case Sleep would
I believe that 99% uses of sleep/ticker actually want monotonic time.
And what happens now is either a bug in Go or in user's programs.
If you run a shall command and set 10min timeout in separate
goroutine. Do you actually mean that it's related to real time in any
way, shape or form? Do you mean that it must sleep for 1 day and 10
min in some cases, and in other abort almost instantly. That's what
such Go code currently says.
That's also what "sleep 10 | command" and various other shell idioms say.
It's also what happens when I tell my android phone "Remind me to 'mail
the electric bill' in 20 minutes".
I think that any function that accepts relative time (time.Sleep,
time.Ticker) must use monotonic time. It is the most reasonable thing
to do. Do you agree?
I do agree that those APIs seem like the most straightforward users of
Net deadlines use absolute time. I think we need to convert the
deadline to relative time ASAP and then use relative sleep on
monotonic clock as well.
I'm not sure whether I agree here or not. From an I/O timeout
think you'd want monotonic time. I'm not actually sure whether epoll and
friends support this, though. From an API standpoint, though, there are
very profound benefits of having an absolute time deadline in terms of code
simplicity. If you only have SetTimeout (which we used to have), it's
unclear what to do when the Write call will result in multiple underlying
write calls. Does each one get the specified timeout? Does every write
have to complete within that amount of time since SetTimeout was called?
The latter seems like what you propose, but would be really hard for users
I do not mean to change semantics of SetDeadline/Timeout calls. I mean
that relative timeout is another (better) way to specify what
SetDeadline does. But other than that it will behave exactly as
Call as SetDeadline(time.Now() + time.Minute) is also clearly broken.
I can not imagine that user wants it to be affected by real time clock
So the SetTimeout(d) will be equivalent to
"SetMonoDeadline(time.MonoNow() + d)".
We can not just say that SetDeadline now accepts monotonic time,
because it will break existing programs. We can introduce something
Actually, though, we can't. Not until Go 2. We can, however, allow the
user to tell (via something like time.SetClock(clock.Monotonic)) us what
they want. In addition to being backward-compatible, I think it'd be the
right thing to do.
Adding even more calls to the net.Conn api is also precisely the opposite
of the simplicity I'd like to see for dealing with clocks. If you'll allow
me to make up statistics for a moment, 99% of programs don't care, and of
the 1% that do, 75% won't break catastrophically. Who cares if a network
connection takes a second longer to time out at midnight once a year?
Unfortunately, something more like 10% of programs *should* care, and we
should make it really easy for them to be correct. The cognitive overhead
and maintenance burden of adding SetMonoDeadline and SetTimeout would seem
to be both too expensive for the people who don't and/or shouldn't care,
and harder to understand what the "right" thing is to do for the people who
There's another important aspect of time that we haven't even gotten to
yet, and that's all of the poor assumptions that distributed systems make
about time. If I send you a timestamp, what does that mean? These are the
places where time really starts to matter, and where the consequences of
getting it wrong can be much higher.
Here is an issue with API that we can not fix
-- if a user adds time.Minute to time.Now(), then time step happens,
then we subtract the result from time.Now(), we get garbage.
Really? I don't think our time arithmetic will ever give you garbage.http://play.golang.org/p/FEK7AA1omh
We just need to define what happens
when you try to sleep a negative amount, which should be easy: you don't
I meant that it is garbage in the sense that from users point of view
it's essentially random value.
Any call to SetDeadline(time.Now().Add(time.Minute)) is equivalent to
We're not talking about race conditions here. It's not a random time, it's
just a time that us subject to outside influence.
As for your sleep-till-midnight use case. This looks like a very
It's a specific example of a reasonably common case. If you're
things to run (system upgrades, a software rollout, cron, email
notifications), you'll often be doing it in terms of wall clock time, so
that a human checking his watch will know when it's going to happen. At
present you're unlikely to get too far off, because leap seconds are the
only thing that should cause a time step in a steady state NTP system, but
you may well write the code in the way I describe (sleep for
target-time.Now() in a loop) because it is the closest analogy to what you'd
do as a human (keep checking your watch until it's time to do your
Ah, I see.
Talking about differences between real and monotonic time, if real
time does not change, it not interesting. Use any, they are the same.
There are also software bugs, administrators and desktop systems with
Ordinary user does not understand what is UTC time and timezone. So
when he travels to -12 timezone, he changes his *time* by -12hrs. Then
he connects to internet and NTP changes his time back by +12hrs. Then
it repeats for the whole travel.
During this half of his Go programs and another half crash with timeouts.
Let's assume for this discussion that time periodically randomly
changes by +/- year.
We didn't design the standard library to assume that someone might be
standing over your DIMMs with a high energy radiation source flipping the
bits in your memory either. Assuming that the underlying system is
terribly broken seems like an irresponsible stance when designing an API.
I want to design an API that makes it easy for software that cares about
the behavior of its time source to behave correctly under normal
circumstances. It is unfortunate that normal circumstances include clock
steps for leap seconds and the occasional clock step or slew when ntpd
regains connectivity, but that's the way things are.
Now what does it mean to do something every midnight?
If the same midnight happens twice, do you want to do something two times?
If from one midnight to the next passes a week of monotonic time, how
the system must behave?
(1) it is not supported by current implementation in any
way, so we can not break anything existing.
Actually, in the current implementation, I believe the API allows you to
sleep until the clock says a specified time pretty easily; what it does not
currently provide is a way to sleep until a certain amount of time has
... until a certain amount of time has actually passed in what time
By actual, I meant real.
I believe in presence of time changes it behaves essentially randomly now.
That would seem to be an overreaction to the facts. If that were the case,
the existing mechanisms for time (in all languages) would have long since
(2) it must necessary
accept absolute time (because if you say sleep for 1 hour, but mean
sleep till midnight, there is no way we can figure your intention
It's true the Sleep(1*time.Hour) carries no intent; however, it is easier to
recover if Sleep(1*time.Hour) sleeps for less than an hour -- the calling
application can always sleep again. You can't go back in time if you
Yes, but on the other hand, the next midnight can suddenly happen next
That's why I say that I can not imagine any sane semantics for such
sleep in presence of chaotic time changes (and if they do not happen,
then all this become trivial and nothing to talk about).
Chaotic time changes? They may happen, but I'm not sure how you could ever
trust anything under such circumstances, including whether your binary was
built with up-to-date objects. I'm interested in the run-of-the-mill time
steps and slews that happen on pretty much every system, and which some
programs need to understand.
So based on all that, I think the plan should be:
1. Convert most existing things to monotonic time (time.Sleep,
time.Ticker). This essentially fixes bugs.
As you said above, time.Sleep carries no intent. Therefore, you can't say
whether this will introduce or fix bugs. I have written at least one
application that uses sleep in the way I describe. Worse, making the change
will not visibly break anybody that was using them in that way, so they may
not notice until it's too late.
It does not work now. So it's not a problem :)
My application most certainly does work now. Even in the presence of clock
steps. It has the precise behavior that I wish of it. It would not be
improved by switching to monotonic time; in fact, if I implemented my API,
I would probably explicitly tell the time API to use the system clock just
for clarity of purpose.
2. Introduce a function to sleep till specified real time, e.g.
I think these introductions would be a good start. Perhaps introducing them
now and giving users until go 2 to start using them would allow you to make
Sleep and Ticker use monotonic time without breaking anybody. Of course,
then the suggestion would be to make SleepMono and NewMonoTimer... but now
we have a major API addition. Thus my suggestion to introduce a Clock
primitive, so you could call time.SetClock(clk) and make all calls to
time.Sleep and time.NewTimer use it (or call time.New(clk).Sleep and such to
not change out the clock used by the entire package). In this way, you can
maintain the current behavior in perpetuity, while still allowing users who
need one behavior or the other to specify it.
You can use the clock in your program, but you can't fix all the
packages you use.
if I could time.SetClock(time.Monotonic), it would make them all use the
monotonic clock. I'm not sure what you mean by "fix," as this implies that
they're broken. What evidence do you have that libraries in Go are widely
broken with respect to time?
3. Convert socket deadlines to monotonic time, and probably introduce
SetTimeout(time.Duration) and say that if you use SetDeadline you will
be skrewed up in presence of time steps.
I'm not convinced about this part quite yet; see above.
I am not proposing new behavior (like timeout for each separate net
call). SetTimeout is just a non-broken way to communicate when you
want the deadline to happen.
If we're talking about clarity of intent here, let's consider the
conn := net.Dial(tcp, "google.com:80")
conn.Write("GET / HTTP/1.1\r\n\r\n")
buf := new(bytes.Buffer)
How long could this take after the connection is established?
1 minute: if you assume that a deadline for the connection is set.
2 minutes: if you assume that the Write call and the entirety of the Copy
each have their own 1 minute timeout
Forever: if you assume that each read syscall and each write syscall
individually have a 1 minute timeout.
If you change that to conn.SetDeadline(time.Now().Add(1*time.Minute)), it
is clear that it is intended to take at most 1 minute to complete after the
connection is established. If the time library has been switched to using
a monotonic clock, this works correctly in the presence of clock steps (at
the cost of making time.Now() diverge from the system clock).
4. Expose monotonic time to user, e.g. time.MonoNow().
With a clock primitive, you can provide these directly from the clocks:
"os/clock".Monotonic.Now() etc. I actually don't think time.MonoNow would
be a good API, because it would seem to correlate to Now() which returns a
Time, and MonoNow would actually need to be a counter, e.g. uint64.
Well, I don't have a strong position right now about how exactly the
API must look like. But FWIW MonoTime() can return Time from some
unspecified point in time.
I think the shape of the API is critical to making it easy to use, and I
think maintaining the current API surfaces is possible without sacrificing
correctness for the clients who require it.
Does it sound good to you?
On Aug 23, 2013 5:41 AM, "Rob Pike" wrote:
On Fri, Aug 23, 2013 at 7:06 PM, Dmitry Vyukov <firstname.lastname@example.org
I think time.Sleep, time.Ticker, etc should simply always use
I've been waiting for someone to say that. I figured I was missing
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to email@example.com.
For more options, visit https://groups.google.com/groups/opt_out.