Skip to content

Commit

Permalink
[host] windows: use millisecond precision for BootTime()
Browse files Browse the repository at this point in the history
Previously, system uptime is truncated to seconds, and then the
subtraction from `time.Now()` is performed. Because uptime does not roll
over to the next second at the same instant as `time.Now()`, then
`BootTime()` ends up not being precise, and often varies by 1 second.

This commit does the subtraction before truncating to seconds, which
results in a significantly lower chance of variance in `BootTime()`.
  • Loading branch information
jefferbrecht committed Jan 4, 2023
1 parent 2fb67aa commit a5ecb9b
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 3 deletions.
4 changes: 4 additions & 0 deletions host/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,7 @@ func SensorsTemperatures() ([]TemperatureStat, error) {
func timeSince(ts uint64) uint64 {
return uint64(time.Now().Unix()) - ts
}

func timeSinceMillis(ts uint64) uint64 {
return uint64(time.Now().UnixMilli()) - ts
}
14 changes: 11 additions & 3 deletions host/host_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,14 @@ func numProcs(ctx context.Context) (uint64, error) {
}

func UptimeWithContext(ctx context.Context) (uint64, error) {
up, err := uptimeMillis()
if err != nil {
return 0, err
}
return uint64((time.Duration(up) * time.Millisecond).Seconds()), nil
}

func uptimeMillis() (uint64, error) {
procGetTickCount := procGetTickCount64
err := procGetTickCount64.Find()
if err != nil {
Expand All @@ -112,7 +120,7 @@ func UptimeWithContext(ctx context.Context) (uint64, error) {
if lastErr != 0 {
return 0, lastErr
}
return uint64((time.Duration(r1) * time.Millisecond).Seconds()), nil
return uint64(r1), nil
}

// cachedBootTime must be accessed via atomic.Load/StoreUint64
Expand All @@ -123,11 +131,11 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) {
if t != 0 {
return t, nil
}
up, err := Uptime()
up, err := uptimeMillis()
if err != nil {
return 0, err
}
t = timeSince(up)
t = uint64((time.Duration(timeSinceMillis(up)) * time.Millisecond).Seconds())
atomic.StoreUint64(&cachedBootTime, t)
return t, nil
}
Expand Down

0 comments on commit a5ecb9b

Please sign in to comment.