time: use monotonic clock to measure elapsed time #12914

Closed
tsuna opened this Issue Oct 13, 2015 · 154 comments

Comments

Projects
None yet
@tsuna
Contributor

tsuna commented Oct 13, 2015

Go's standard library doesn't provide any API to access a monotonic clock source, which means one can't reliably time how long an operation takes without copy-pasting or importing some low-level platform-dependent code such as the clock package at https://github.com/davecheney/junk.

This API doesn't necessarily need to return a time.Time, just returning a number of nanoseconds as a uint64 would be enough, kinda like Java's System.nanoTime().

@adg

This comment has been minimized.

Show comment Hide comment
@adg

adg Oct 13, 2015

Contributor

Do we have a monotonic clock source we can export?

If not, why should this be in the standard library and not just an
importable package?

On 13 October 2015 at 12:42, Benoit Sigoure notifications@github.com
wrote:

Go's standard library doesn't provide any API to access a monotonic clock
source, which means one can't reliably time how long an operation takes
without copy-pasting or importing some low-level platform-dependent code
such as the clock package at https://github.com/davecheney/junk.

This API doesn't necessarily need to return a time.Time, just returning a
number of nanoseconds as a uint64 would be enough, kinda like Java's
System.nanoTime()
http://docs.oracle.com/javase/8/docs/api/java/lang/System.html#nanoTime--
.


Reply to this email directly or view it on GitHub
#12914.

Contributor

adg commented Oct 13, 2015

Do we have a monotonic clock source we can export?

If not, why should this be in the standard library and not just an
importable package?

On 13 October 2015 at 12:42, Benoit Sigoure notifications@github.com
wrote:

Go's standard library doesn't provide any API to access a monotonic clock
source, which means one can't reliably time how long an operation takes
without copy-pasting or importing some low-level platform-dependent code
such as the clock package at https://github.com/davecheney/junk.

This API doesn't necessarily need to return a time.Time, just returning a
number of nanoseconds as a uint64 would be enough, kinda like Java's
System.nanoTime()
http://docs.oracle.com/javase/8/docs/api/java/lang/System.html#nanoTime--
.


Reply to this email directly or view it on GitHub
#12914.

@tsuna

This comment has been minimized.

Show comment Hide comment
@tsuna

tsuna Oct 13, 2015

Contributor

Why should this be in the standard library: because it's a pretty fundamental thing, especially in a language geared towards systems programming. I see a lot of people timing how long operations take using time.Now() and subtracting two time.Time objects, and I always end up saying "this is not a correct way of measuring how much time elapsed" but don't have a clear alternative to propose.

Come on, even Java has it.

Contributor

tsuna commented Oct 13, 2015

Why should this be in the standard library: because it's a pretty fundamental thing, especially in a language geared towards systems programming. I see a lot of people timing how long operations take using time.Now() and subtracting two time.Time objects, and I always end up saying "this is not a correct way of measuring how much time elapsed" but don't have a clear alternative to propose.

Come on, even Java has it.

@adg

This comment has been minimized.

Show comment Hide comment
@adg

adg Oct 13, 2015

Contributor

I see a lot of people timing how long operations take using time.Now() and subtracting two time.Time objects, and I always end up saying "this is not a correct way of measuring how much time elapsed"

Got any concrete examples?

Contributor

adg commented Oct 13, 2015

I see a lot of people timing how long operations take using time.Now() and subtracting two time.Time objects, and I always end up saying "this is not a correct way of measuring how much time elapsed"

Got any concrete examples?

@tsuna

This comment has been minimized.

Show comment Hide comment
@tsuna

tsuna Oct 13, 2015

Contributor

Any concrete examples of ..? People using time.Now() or it being wrong because it doesn't take into account changes made to the system time?

Contributor

tsuna commented Oct 13, 2015

Any concrete examples of ..? People using time.Now() or it being wrong because it doesn't take into account changes made to the system time?

@adg

This comment has been minimized.

Show comment Hide comment
@adg

adg Oct 13, 2015

Contributor

I suppose what I'm getting at is this: If there's a broad need for such a package, why isn't there one that people are already using?

Contributor

adg commented Oct 13, 2015

I suppose what I'm getting at is this: If there's a broad need for such a package, why isn't there one that people are already using?

@extemporalgenome

This comment has been minimized.

Show comment Hide comment
@extemporalgenome

extemporalgenome Oct 13, 2015

This API doesn't necessarily need to return a time.Time, just returning a number of nanoseconds as a uint64 would be enough, kinda like Java's System.nanoTime().

time.Duration happens to represent a 64-bit quantity nanoseconds, and, unless there's some large problem with it, should be favored as the return type for any monotonic duration handling functions.

This API doesn't necessarily need to return a time.Time, just returning a number of nanoseconds as a uint64 would be enough, kinda like Java's System.nanoTime().

time.Duration happens to represent a 64-bit quantity nanoseconds, and, unless there's some large problem with it, should be favored as the return type for any monotonic duration handling functions.

@rakyll rakyll added this to the Unplanned milestone Oct 13, 2015

@taruti

This comment has been minimized.

Show comment Hide comment
@taruti

taruti Oct 21, 2015

Contributor

I think there are two things:

A) A proper monotonic clock package (there are multiple 3rd party ones)

B) Measuring elapsed time on systems where system time may leap to either direction

B is simpler. Either ensure and document that time.Since works
even with clock shifts or define new API like:

type MeasureStart struct { ... }
func (*MeasureStart)Start()
func (*MeasureStart)Elapsed() time.Duration
Contributor

taruti commented Oct 21, 2015

I think there are two things:

A) A proper monotonic clock package (there are multiple 3rd party ones)

B) Measuring elapsed time on systems where system time may leap to either direction

B is simpler. Either ensure and document that time.Since works
even with clock shifts or define new API like:

type MeasureStart struct { ... }
func (*MeasureStart)Start()
func (*MeasureStart)Elapsed() time.Duration
@crawshaw

This comment has been minimized.

Show comment Hide comment
@crawshaw

crawshaw Oct 23, 2015

Contributor

On what platforms is time.Now() not monotonic? For linux/amd64, time.Now is implemented by runtime·nanotime, which is calling clock_gettime (via VDSO) with CLOCK_MONOTONIC. I see similar calls being used on linux/arm, openbsd, freebsd, etc.

Instead of a new interface, can we document time.Now as monotonic?

Contributor

crawshaw commented Oct 23, 2015

On what platforms is time.Now() not monotonic? For linux/amd64, time.Now is implemented by runtime·nanotime, which is calling clock_gettime (via VDSO) with CLOCK_MONOTONIC. I see similar calls being used on linux/arm, openbsd, freebsd, etc.

Instead of a new interface, can we document time.Now as monotonic?

@ianlancetaylor

This comment has been minimized.

Show comment Hide comment
@ianlancetaylor

ianlancetaylor Oct 23, 2015

Contributor

@crawshaw time.Now is not monotonic on any platform that supports settimeofday. On amd64 GNU/Linux time.Now does not actually use CLOCK_MONOTONIC, it uses CLOCK_REALTIME. It's runtime.nanotime that uses CLOCK_MONOTONIC.

Contributor

ianlancetaylor commented Oct 23, 2015

@crawshaw time.Now is not monotonic on any platform that supports settimeofday. On amd64 GNU/Linux time.Now does not actually use CLOCK_MONOTONIC, it uses CLOCK_REALTIME. It's runtime.nanotime that uses CLOCK_MONOTONIC.

@ianlancetaylor

This comment has been minimized.

Show comment Hide comment
@ianlancetaylor

ianlancetaylor Oct 23, 2015

Contributor

Sorry, I somehow missed that you mentioned nanotime yourself. That's not what implements time.Now, though, that is implemented by time·now.

Contributor

ianlancetaylor commented Oct 23, 2015

Sorry, I somehow missed that you mentioned nanotime yourself. That's not what implements time.Now, though, that is implemented by time·now.

@crawshaw

This comment has been minimized.

Show comment Hide comment
@crawshaw

crawshaw Oct 23, 2015

Contributor

Ah right, thanks. I got confused by //go:linkname time_runtimeNano time.runtimeNano, which I misread as implementing time.Now

Contributor

crawshaw commented Oct 23, 2015

Ah right, thanks. I got confused by //go:linkname time_runtimeNano time.runtimeNano, which I misread as implementing time.Now

@alexbrainman

This comment has been minimized.

Show comment Hide comment
@alexbrainman

alexbrainman Oct 23, 2015

Member

time.Now() is monotonic on windows. We use undocumented way to fetch time, but it is monotonic as far as I know. @dvyukov to confirm.

Alex

Member

alexbrainman commented Oct 23, 2015

time.Now() is monotonic on windows. We use undocumented way to fetch time, but it is monotonic as far as I know. @dvyukov to confirm.

Alex

@tsuna

This comment has been minimized.

Show comment Hide comment
@tsuna

tsuna Oct 23, 2015

Contributor

On Mon, Oct 12, 2015 at 9:07 PM, Andrew Gerrand wrote:

I suppose what I'm getting at is this: If there's a broad need for such a package, why isn't there one that people are already using?

Because people incorrectly assume that time only moves forward? It's an extremely common mistake that even at Google we were trying to hammer in people's head. When you see the large impact that things such as leap seconds have (including at Google), it's easy to see this is a well known problem but also a recurring problem.

How is it that a language geared towards systems programming that comes with such a rich standard library offers no standard way of measuring time correctly?

Look at gRPC, every single use of time.Now() there is buggy because it implicitly assumes that time only moves forward and at a constant pace, neither of which is true for CLOCK_REALTIME. Pretty much any distributed systems code that uses time.Now() other than for printing the current time is subtly buggy. And there is a lot of it. And it's there chiefly because there is no alternative in the standard library to get monotonic time so people don't even think about it.

Contributor

tsuna commented Oct 23, 2015

On Mon, Oct 12, 2015 at 9:07 PM, Andrew Gerrand wrote:

I suppose what I'm getting at is this: If there's a broad need for such a package, why isn't there one that people are already using?

Because people incorrectly assume that time only moves forward? It's an extremely common mistake that even at Google we were trying to hammer in people's head. When you see the large impact that things such as leap seconds have (including at Google), it's easy to see this is a well known problem but also a recurring problem.

How is it that a language geared towards systems programming that comes with such a rich standard library offers no standard way of measuring time correctly?

Look at gRPC, every single use of time.Now() there is buggy because it implicitly assumes that time only moves forward and at a constant pace, neither of which is true for CLOCK_REALTIME. Pretty much any distributed systems code that uses time.Now() other than for printing the current time is subtly buggy. And there is a lot of it. And it's there chiefly because there is no alternative in the standard library to get monotonic time so people don't even think about it.

@rsc

This comment has been minimized.

Show comment Hide comment
@rsc

rsc Oct 24, 2015

Contributor

How is it that a language geared towards systems programming that comes with such a rich standard library offers no standard way of measuring time correctly?

I expect that if you care that much about time you will run your system clocks correctly. On a well-run system, time does only move forward and at a constant (enough) pace.

When you see the large impact that things such as leap seconds have (including at Google), it's easy to see this is a well known problem but also a recurring problem.

I don't understand this comment. Leap seconds don't exist at Google.

It is true that if you use time.Now to measure time during a leap smear then your measurements may be off by approximately 0.001%. But time will still be monotonic.

Contributor

rsc commented Oct 24, 2015

How is it that a language geared towards systems programming that comes with such a rich standard library offers no standard way of measuring time correctly?

I expect that if you care that much about time you will run your system clocks correctly. On a well-run system, time does only move forward and at a constant (enough) pace.

When you see the large impact that things such as leap seconds have (including at Google), it's easy to see this is a well known problem but also a recurring problem.

I don't understand this comment. Leap seconds don't exist at Google.

It is true that if you use time.Now to measure time during a leap smear then your measurements may be off by approximately 0.001%. But time will still be monotonic.

@rsc rsc changed the title from runtime: Add a new API to access a monotonic clock source to runtime: time: expose monotonic clock source Oct 24, 2015

@dvyukov

This comment has been minimized.

Show comment Hide comment
@dvyukov

dvyukov Oct 24, 2015

Member

I expect that if you care that much about time you will run your system clocks correctly. On a well-run system, time does only move forward and at a constant (enough) pace.

How about programs that run on client machines? Or server software that you sells to clients?

Member

dvyukov commented Oct 24, 2015

I expect that if you care that much about time you will run your system clocks correctly. On a well-run system, time does only move forward and at a constant (enough) pace.

How about programs that run on client machines? Or server software that you sells to clients?

@dvyukov

This comment has been minimized.

Show comment Hide comment
@dvyukov

dvyukov Oct 24, 2015

Member

time.Now() is monotonic on windows. We use undocumented way to fetch time, but it is monotonic as far as I know. @dvyukov to confirm.

I don't think we return monotonic time from time.Now on windows. This would be a bug, because time.Now should return system time which can be changed by user.
The shared page contains InterruptTime, this time is monotonic and we use it for runtime.nanotime; and SystemTime, this time is not monotonic and we use for time.Now.

Member

dvyukov commented Oct 24, 2015

time.Now() is monotonic on windows. We use undocumented way to fetch time, but it is monotonic as far as I know. @dvyukov to confirm.

I don't think we return monotonic time from time.Now on windows. This would be a bug, because time.Now should return system time which can be changed by user.
The shared page contains InterruptTime, this time is monotonic and we use it for runtime.nanotime; and SystemTime, this time is not monotonic and we use for time.Now.

@alexbrainman

This comment has been minimized.

Show comment Hide comment
@alexbrainman

alexbrainman Oct 24, 2015

Member

What Dmitry said.

Alex

Member

alexbrainman commented Oct 24, 2015

What Dmitry said.

Alex

@tsuna

This comment has been minimized.

Show comment Hide comment
@tsuna

tsuna Oct 25, 2015

Contributor

On Fri, Oct 23, 2015 at 9:50 PM, Russ Cox wrote:

I don't understand this comment. Leap seconds don't exist at Google.

I was working just down the hall from where you were in B43 in 2008, when the leap second smearing scheme was devised, because everybody remembered all too well how all hell broke loose for the previous leap second.

Contributor

tsuna commented Oct 25, 2015

On Fri, Oct 23, 2015 at 9:50 PM, Russ Cox wrote:

I don't understand this comment. Leap seconds don't exist at Google.

I was working just down the hall from where you were in B43 in 2008, when the leap second smearing scheme was devised, because everybody remembered all too well how all hell broke loose for the previous leap second.

@driskell

This comment has been minimized.

Show comment Hide comment
@driskell

driskell Feb 21, 2016

I'm not quite understanding, why the time and net package can get access to a monotonic clock, through runtime package, but nothing else can. Surely it would be beneficial to allow others to write packages that have similar capabilities to the time and net standard libraries? It seems the protections of the monotonic clock are currently limited to the standard library and inaccessible to all other libraries.

I can understand the arguments about clocks should never go backwards but the fact that time and net is already using monotonic time, in my opinion, means that discussion was had a long time ago and the argument for monotonic time won out. It's unfortunate it's been kept inaccessible to everyone else.

Is it feasible and would it be acceptable to expose a runtime.NanoTime? That name is likely misleading though but it seems reasonable to me. (https://github.com/golang/go/blob/master/src/runtime/time.go#L296)

I'm not quite understanding, why the time and net package can get access to a monotonic clock, through runtime package, but nothing else can. Surely it would be beneficial to allow others to write packages that have similar capabilities to the time and net standard libraries? It seems the protections of the monotonic clock are currently limited to the standard library and inaccessible to all other libraries.

I can understand the arguments about clocks should never go backwards but the fact that time and net is already using monotonic time, in my opinion, means that discussion was had a long time ago and the argument for monotonic time won out. It's unfortunate it's been kept inaccessible to everyone else.

Is it feasible and would it be acceptable to expose a runtime.NanoTime? That name is likely misleading though but it seems reasonable to me. (https://github.com/golang/go/blob/master/src/runtime/time.go#L296)

@abligh abligh referenced this issue in hashicorp/raft Mar 25, 2016

Open

Make leader leases actual leases #108

Arista-Jenkins pushed a commit to aristanetworks/goarista that referenced this issue May 2, 2016

atime: New package to provide access to a fast monotonic clock source.
This package fills in the gap of the Go standard library discussed in
golang/go#12914.

Change-Id: Icefcb17a11a7061be369318b50ca0cd55c53e7da
@tsuna

This comment has been minimized.

Show comment Hide comment
@tsuna

tsuna May 2, 2016

Contributor

For those who need a solution to this problem, here's a way to expose Go's own runtime.nanotime(), which avoids the hassle of reimplementing an Nth solution that is fast & cross-platform: aristanetworks/goarista@46272bf

Contributor

tsuna commented May 2, 2016

For those who need a solution to this problem, here's a way to expose Go's own runtime.nanotime(), which avoids the hassle of reimplementing an Nth solution that is fast & cross-platform: aristanetworks/goarista@46272bf

@rsc

This comment has been minimized.

Show comment Hide comment
@rsc

rsc Nov 8, 2016

Contributor

Too late for new API in Go 1.8.

Contributor

rsc commented Nov 8, 2016

Too late for new API in Go 1.8.

@rsc rsc modified the milestones: Go1.9Early, Go1.8 Nov 8, 2016

@rsc

This comment has been minimized.

Show comment Hide comment
@rsc

rsc Nov 8, 2016

Contributor

Note that we don't actually have monotonic time on all systems. Right now it is best effort only (on systems where we have it, the runtime uses it).

Contributor

rsc commented Nov 8, 2016

Note that we don't actually have monotonic time on all systems. Right now it is best effort only (on systems where we have it, the runtime uses it).

@RaduBerinde RaduBerinde referenced this issue in cockroachdb/cockroach Nov 9, 2016

Closed

storage: panic: mutex held for > 100ms #10567

@vincentbernat

This comment has been minimized.

Show comment Hide comment
@vincentbernat

vincentbernat Jan 27, 2017

@jayschwa

This comment has been minimized.

Show comment Hide comment
@jayschwa

jayschwa Jan 27, 2017

Contributor

How much performance is gained by using the packed (and harder to understand) format versus adding a new, independent field for monotonic time?

Contributor

jayschwa commented Jan 27, 2017

How much performance is gained by using the packed (and harder to understand) format versus adding a new, independent field for monotonic time?

@bradfitz

This comment has been minimized.

Show comment Hide comment
@bradfitz

bradfitz Jan 27, 2017

Owner

@jayschwa, there's no new API, so users don't need to understand it, just as users don't need to understand the internals of the garbage collector. The main advantage of @rsc's proposed representation is that it doesn't change the memory footprint on 64-bit systems because there's already an unused 32-bit padding hole today.

Owner

bradfitz commented Jan 27, 2017

@jayschwa, there's no new API, so users don't need to understand it, just as users don't need to understand the internals of the garbage collector. The main advantage of @rsc's proposed representation is that it doesn't change the memory footprint on 64-bit systems because there's already an unused 32-bit padding hole today.

@doherty

This comment has been minimized.

Show comment Hide comment
@doherty

doherty Jan 27, 2017

What happens when you wanted to do math with monotonic times but unbeknownst to you one of your time.Times lacks a monotonic time, so you get wall clock semantics? Are there any such cases? I'm thinking of situations where one of your time.Times is obtained from outside the process, and you're doing math on it: perhaps your operation's start time is stored in a database, and now you add a timeout to obtain a deadline -- but the time in the DB won't have a monotonic time (or, at least, it won't make sense).

doherty commented Jan 27, 2017

What happens when you wanted to do math with monotonic times but unbeknownst to you one of your time.Times lacks a monotonic time, so you get wall clock semantics? Are there any such cases? I'm thinking of situations where one of your time.Times is obtained from outside the process, and you're doing math on it: perhaps your operation's start time is stored in a database, and now you add a timeout to obtain a deadline -- but the time in the DB won't have a monotonic time (or, at least, it won't make sense).

@minux

This comment has been minimized.

Show comment Hide comment
@minux

minux Jan 28, 2017

Member
Member

minux commented Jan 28, 2017

@alexmullins

This comment has been minimized.

Show comment Hide comment
@alexmullins

alexmullins Feb 2, 2017

@rsc,
Just read the design doc. Looks good. I like that the API is staying simple. I noticed a small spelling mistake in the new documentation section 'Monotonic Clocks':

(If either t or u or contains no monotonic clock reading, these operations use the wall clock readings.)

There's one too many 'or' in there.

@rsc,
Just read the design doc. Looks good. I like that the API is staying simple. I noticed a small spelling mistake in the new documentation section 'Monotonic Clocks':

(If either t or u or contains no monotonic clock reading, these operations use the wall clock readings.)

There's one too many 'or' in there.

@rsc

This comment has been minimized.

Show comment Hide comment
@rsc

rsc Feb 3, 2017

Contributor

@alexmullins Thanks, fixed two other typos as well.

Contributor

rsc commented Feb 3, 2017

@alexmullins Thanks, fixed two other typos as well.

@gopherbot

This comment has been minimized.

Show comment Hide comment
@gopherbot

gopherbot Feb 3, 2017

CL https://golang.org/cl/36255 mentions this issue.

CL https://golang.org/cl/36255 mentions this issue.

@bradfitz

This comment has been minimized.

Show comment Hide comment
@bradfitz

bradfitz Feb 3, 2017

Owner

NTP's epoch is 1900. That might be a safer option than 1950.

Owner

bradfitz commented Feb 3, 2017

NTP's epoch is 1900. That might be a safer option than 1950.

@gopherbot gopherbot closed this in 0e33559 Feb 3, 2017

@rsc rsc changed the title from proposal: time: use monotonic clock to measure elapsed time to time: use monotonic clock to measure elapsed time Feb 3, 2017

@rsc rsc modified the milestones: Go1.9, Proposal Feb 3, 2017

@cespare

This comment has been minimized.

Show comment Hide comment
@cespare

cespare Feb 3, 2017

Contributor

Looks like the current code on master uses 1885-2157 as the range of wall times when monotonic time is present.

Contributor

cespare commented Feb 3, 2017

Looks like the current code on master uses 1885-2157 as the range of wall times when monotonic time is present.

@rsc

This comment has been minimized.

Show comment Hide comment
@rsc

rsc Feb 3, 2017

Contributor

OK, this is checked in for Go 1.9. I moved the internal epoch to 1885 (max year 2157) to avoid any possible problem with NTP-epoch-derived times. I also adjusted the design doc to reflect this change and some minor encoding changes.

Thanks for the constructive conversation everyone.

Contributor

rsc commented Feb 3, 2017

OK, this is checked in for Go 1.9. I moved the internal epoch to 1885 (max year 2157) to avoid any possible problem with NTP-epoch-derived times. I also adjusted the design doc to reflect this change and some minor encoding changes.

Thanks for the constructive conversation everyone.

@orivej

This comment has been minimized.

Show comment Hide comment
@orivej

orivej Feb 3, 2017

  1. The merged implementation changes the meaning of time.Now().Sub(old) when now and old are separated by system suspend and resume: it used to calculate real time difference and now that difference is reduced by the duration the system was suspended. Shouldn't time use monotonic real time source when available, and if so, can runtime.nanotime be redefined to read from that source, or should there be a new clock specifically for time.Now() to read from?

  2. Is there an explanation for + 1 in nanotime() - startNano + 1 in the design doc? If it is needed, why startNano is not reduced by 1 instead?

orivej commented Feb 3, 2017

  1. The merged implementation changes the meaning of time.Now().Sub(old) when now and old are separated by system suspend and resume: it used to calculate real time difference and now that difference is reduced by the duration the system was suspended. Shouldn't time use monotonic real time source when available, and if so, can runtime.nanotime be redefined to read from that source, or should there be a new clock specifically for time.Now() to read from?

  2. Is there an explanation for + 1 in nanotime() - startNano + 1 in the design doc? If it is needed, why startNano is not reduced by 1 instead?

@rsc

This comment has been minimized.

Show comment Hide comment
@rsc

rsc Feb 3, 2017

Contributor

@orivej,

  1. Whether time.Since(start) includes "system suspended" time depends on the underlying OS's monotonic clock, but in general it's tricky to add that time into the clock since you can't take it back if you later find out you are wrong. My preference here would be to do the same thing on all operating systems, whatever that is. My guess is that all operating systems can provide the current semantics but that not all can provide the "include suspended time" semantics.

    It seems to me that if you want to include time while the computer was off, you're really talking about wall times, so the fix would be to flip into wall mode by recording 'start := time.Now().AddDate(0, 0, 0)', putting up with the fact that time.Since(start) might then return negative elapsed times.

  2. The +1 is just to make sure that tests never see a 0 monotonic time, since I used GetMono(&t) == 0 to say that there's no monotonic time. It's only for testing, and even in that context it's probably unnecessary, but also harmless.

Contributor

rsc commented Feb 3, 2017

@orivej,

  1. Whether time.Since(start) includes "system suspended" time depends on the underlying OS's monotonic clock, but in general it's tricky to add that time into the clock since you can't take it back if you later find out you are wrong. My preference here would be to do the same thing on all operating systems, whatever that is. My guess is that all operating systems can provide the current semantics but that not all can provide the "include suspended time" semantics.

    It seems to me that if you want to include time while the computer was off, you're really talking about wall times, so the fix would be to flip into wall mode by recording 'start := time.Now().AddDate(0, 0, 0)', putting up with the fact that time.Since(start) might then return negative elapsed times.

  2. The +1 is just to make sure that tests never see a 0 monotonic time, since I used GetMono(&t) == 0 to say that there's no monotonic time. It's only for testing, and even in that context it's probably unnecessary, but also harmless.

@gopherbot

This comment has been minimized.

Show comment Hide comment
@gopherbot

gopherbot Feb 5, 2017

CL https://golang.org/cl/36334 mentions this issue.

CL https://golang.org/cl/36334 mentions this issue.

gopherbot pushed a commit that referenced this issue Feb 5, 2017

time: Fix typo in Time.String() description.
Refs #12914.

Change-Id: Iadac4cbef70db6a95b47f86eaffcfc63bfdb8e90
Reviewed-on: https://go-review.googlesource.com/36334
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
@neild

This comment has been minimized.

Show comment Hide comment
@neild

neild Mar 1, 2017

Contributor

I'm looking at some code which assumes that times truncated to the same time are equal. Simplified:

func main() {
        t1 := time.Now().Truncate(1 * time.Second)
        t2 := time.Now().Truncate(1 * time.Second)
        h1, m1, s1 := t1.Clock()
        h2, m2, s2 := t2.Clock()
        if h1 == h2 && m1 == m2 && s1 == s2 {
                if !t1.Equal(t2) {
                        fmt.Printf("BUG: times truncated to the same second, but are not equal:\n%v\n%v\n", t1, t2)
                }
        }
}

The actual code is mapping times to windows; it assumes that all times within a given window will truncate to the same time.

This doesn't seem unreasonable. Should Truncate discard the monotonic time component?

Contributor

neild commented Mar 1, 2017

I'm looking at some code which assumes that times truncated to the same time are equal. Simplified:

func main() {
        t1 := time.Now().Truncate(1 * time.Second)
        t2 := time.Now().Truncate(1 * time.Second)
        h1, m1, s1 := t1.Clock()
        h2, m2, s2 := t2.Clock()
        if h1 == h2 && m1 == m2 && s1 == s2 {
                if !t1.Equal(t2) {
                        fmt.Printf("BUG: times truncated to the same second, but are not equal:\n%v\n%v\n", t1, t2)
                }
        }
}

The actual code is mapping times to windows; it assumes that all times within a given window will truncate to the same time.

This doesn't seem unreasonable. Should Truncate discard the monotonic time component?

@shurcooL

This comment has been minimized.

Show comment Hide comment
@shurcooL

shurcooL Mar 1, 2017

Member

@neild A relevant open issue is #18991.

Member

shurcooL commented Mar 1, 2017

@neild A relevant open issue is #18991.

shurcooL added a commit to google/go-github that referenced this issue Mar 1, 2017

Modify time first, round after (and strip additional precision).
I've noticed that TestDo_rateLimit_noNetworkCall test fails on Go
master with the following error:

	--- FAIL: TestDo_rateLimit_noNetworkCall (0.00s)
		github_test.go:549: rateLimitErr rate reset = 2017-02-25 01:49:01 +0000 UTC, want 2017-02-25 01:49:01 +0000 UTC m=+60.206993003

(Source: https://travis-ci.org/google/go-github/jobs/205180544.)

This is due to changes in Go 1.9 to perform monotonic elapsed time
measurements. See golang/go#12914 and
https://golang.org/design/12914-monotonic for full details.

Make the test pass by modifying time first, round after, and strip
the monotonic clock reading by using AddDate(0, 0, 0). Doing that
eliminates the unwanted additional monotonic precision from wanted
time, making the expected time equality true.

@samuelkarp samuelkarp referenced this issue in moby/moby May 3, 2017

Merged

Add awslogs multiline support #30891

borkmann added a commit to cilium/cilium that referenced this issue May 27, 2017

pkg, bpf: add api to return monotonic clock
This adds an API that we can use to compare values against bpf_ktime_get_ns()
BPF helper for the timeouts. Looks like golang doesn't offer such an interface,
so we need to add a cgo version right here. Probably also better to not rely
on go internals should they once change their clock source internally, etc.

Related: golang/go#12914

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>

tgraf added a commit to cilium/cilium that referenced this issue May 27, 2017

pkg, bpf: add api to return monotonic clock
This adds an API that we can use to compare values against bpf_ktime_get_ns()
BPF helper for the timeouts. Looks like golang doesn't offer such an interface,
so we need to add a cgo version right here. Probably also better to not rely
on go internals should they once change their clock source internally, etc.

Related: golang/go#12914

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>

@Yawning Yawning referenced this issue in katzenpost/core Jul 11, 2017

Closed

Implement a monotonic time source. #6

@jaffee jaffee referenced this issue in pilosa/tools Aug 2, 2017

Closed

Use monotonic time for benchmark timing #48

@gopherbot gopherbot locked and limited conversation to collaborators Mar 1, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.