[host]: add EnableBootTimeCache function

pull/1579/head
shirou 1 year ago
parent df3c7bdec0
commit b10acd4894

@ -109,6 +109,17 @@ As of v3.23.6, it is now possible to pass a path location using `context`: impor
First priority is given to the value set in `context`, then the value from the environment variable, and finally the default location.
### Caching
As of v3.24.1, it is now possible to cached some values. These values default to false, not cached.
Be very careful that enabling the cache may cause inconsistencies. For example, if you enable caching of boottime on Linux, be aware that unintended values may be returned if [the boottime is changed by NTP after booted](https://github.com/shirou/gopsutil/issues/1070#issuecomment-842512782).
- `host`
- EnableBootTimeCache
- `process`
- EnableBootTimeCache
## Documentation
See https://pkg.go.dev/github.com/shirou/gopsutil/v3 or https://godocs.io/github.com/shirou/gopsutil/v3

@ -62,6 +62,13 @@ func (t TemperatureStat) String() string {
return string(s)
}
var enableBootTimeCache bool
// EnableBootTimeCache change cache behavior of BootTime. If true, cache BootTime value. Default is false.
func EnableBootTimeCache(enable bool) {
enableBootTimeCache = enable
}
func Info() (*InfoStat, error) {
return InfoWithContext(context.Background())
}

@ -14,16 +14,20 @@ import (
var cachedBootTime uint64
func BootTimeWithContext(ctx context.Context) (uint64, error) {
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
if enableBootTimeCache {
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
}
}
tv, err := unix.SysctlTimeval("kern.boottime")
if err != nil {
return 0, err
}
atomic.StoreUint64(&cachedBootTime, uint64(tv.Sec))
if enableBootTimeCache {
atomic.StoreUint64(&cachedBootTime, uint64(tv.Sec))
}
return uint64(tv.Sec), nil
}

@ -71,7 +71,7 @@ func numProcs(ctx context.Context) (uint64, error) {
}
func BootTimeWithContext(ctx context.Context) (uint64, error) {
return common.BootTimeWithContext(ctx)
return common.BootTimeWithContext(ctx, enableBootTimeCache)
}
func UptimeWithContext(ctx context.Context) (uint64, error) {

@ -195,3 +195,17 @@ func TestPlatformInformation(t *testing.T) {
t.Logf("PlatformInformation(): %v, %v, %v", platform, family, version)
}
func BenchmarkBootTimeWithCache(b *testing.B) {
EnableBootTimeCache(true)
for i := 0; i < b.N; i++ {
BootTime()
}
}
func BenchmarkBootTimeWithoutCache(b *testing.B) {
EnableBootTimeCache(false)
for i := 0; i < b.N; i++ {
BootTime()
}
}

@ -127,16 +127,20 @@ func uptimeMillis() (uint64, error) {
var cachedBootTime uint64
func BootTimeWithContext(ctx context.Context) (uint64, error) {
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
if enableBootTimeCache {
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
}
}
up, err := uptimeMillis()
if err != nil {
return 0, err
}
t = uint64((time.Duration(timeSinceMillis(up)) * time.Millisecond).Seconds())
atomic.StoreUint64(&cachedBootTime, t)
t := uint64((time.Duration(timeSinceMillis(up)) * time.Millisecond).Seconds())
if enableBootTimeCache {
atomic.StoreUint64(&cachedBootTime, t)
}
return t, nil
}

@ -12,10 +12,14 @@ import (
"strconv"
"strings"
"sync"
"sync/atomic"
"syscall"
"time"
)
// cachedBootTime must be accessed via atomic.Load/StoreUint64
var cachedBootTime uint64
func DoSysctrl(mib string) ([]string, error) {
cmd := exec.Command("sysctl", "-n", mib)
cmd.Env = getSysctrlEnv(os.Environ())
@ -56,7 +60,14 @@ func NumProcsWithContext(ctx context.Context) (uint64, error) {
return cnt, nil
}
func BootTimeWithContext(ctx context.Context) (uint64, error) {
func BootTimeWithContext(ctx context.Context, enableCache bool) (uint64, error) {
if enableCache {
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
}
}
system, role, err := VirtualizationWithContext(ctx)
if err != nil {
return 0, err
@ -72,7 +83,13 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) {
}
if useStatFile {
return readBootTimeStat(ctx)
t, err := readBootTimeStat(ctx)
if err != nil {
return 0, err
}
if enableCache {
atomic.StoreUint64(&cachedBootTime, t)
}
}
filename := HostProcWithContext(ctx, "uptime")
@ -90,6 +107,11 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) {
}
currentTime := float64(time.Now().UnixNano()) / float64(time.Second)
t := currentTime - b
if enableCache {
atomic.StoreUint64(&cachedBootTime, uint64(t))
}
return uint64(t), nil
}

@ -171,6 +171,13 @@ func (p NumCtxSwitchesStat) String() string {
return string(s)
}
var enableBootTimeCache bool
// EnableBootTimeCache change cache behavior of BootTime. If true, cache BootTime value. Default is false.
func EnableBootTimeCache(enable bool) {
enableBootTimeCache = enable
}
// Pids returns a slice of process ID list which are running now.
func Pids() ([]int32, error) {
return PidsWithContext(context.Background())

@ -1071,7 +1071,7 @@ func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (ui
Iowait: iotime / float64(clockTicks),
}
bootTime, _ := common.BootTimeWithContext(ctx)
bootTime, _ := common.BootTimeWithContext(ctx, enableBootTimeCache)
t, err := strconv.ParseUint(fields[22], 10, 64)
if err != nil {
return 0, 0, nil, 0, 0, 0, nil, err

Loading…
Cancel
Save