As of v3.24.1, gopsutil supports caching for certain values that rarely change but are expensive to compute. Caching can significantly improve performance when these values are queried frequently.
Caching is disabled by default to prevent inconsistencies. Enable caching only when you understand the implications and your use case benefits from it.
Some system information, like boot time, requires:
Reading and parsing system files
Multiple syscalls
String processing
When queried repeatedly (e.g., in monitoring loops), this overhead accumulates. Caching eliminates redundant operations for values that rarely or never change during system runtime.
import ( "sync" "github.com/shirou/gopsutil/v4/host")func main() { host.EnableBootTimeCache(true) var wg sync.WaitGroup for i := 0; i < 100; i++ { wg.Add(1) go func() { defer wg.Done() // Safe to call from multiple goroutines host.BootTime() }() } wg.Wait()}
The cache uses atomic operations (atomic.LoadUint64 and atomic.StoreUint64) which are lock-free and have minimal contention overhead.
Call EnableBootTimeCache(true) at the start of your main() function, before any gopsutil calls.
func main() { host.EnableBootTimeCache(true) process.EnableBootTimeCache(true) // ... rest of application}
2
Document the Decision
If you enable caching, document why and any assumptions about your environment.
// We enable boot time caching because:// 1. This is a long-running monitoring service// 2. We poll metrics every second// 3. Our systems don't use NTP time adjustmentshost.EnableBootTimeCache(true)
3
Consider Your Environment
Evaluate whether your deployment environment is compatible with caching:
Are systems time-synchronized with NTP?
Do containers migrate between hosts?
Are there system restarts or hibernation?
4
Benchmark Your Use Case
Measure the actual performance impact for your specific workload:
func benchmark() { start := time.Now() for i := 0; i < 1000; i++ { host.BootTime() } fmt.Printf("1000 calls took: %v\n", time.Since(start))}// Without cache: ~50ms// With cache: ~0.01ms
Symptom: Boot time changes between callsCause: Caching is disabled (default behavior)Solution: Enable caching if you want consistent values:
host.EnableBootTimeCache(true)
Stale boot time after NTP sync
Symptom: Boot time doesn’t match actual system bootCause: NTP adjusted time after cache was populatedSolution: Either:
Don’t use caching in NTP environments
Restart application after NTP sync
Toggle caching to refresh:
host.EnableBootTimeCache(false)host.EnableBootTimeCache(true)host.BootTime() // Fresh value
Cache not improving performance
Symptom: No measurable performance differenceCause: Boot time isn’t the bottleneck, or you’re not calling it frequentlySolution: Profile your application to find actual bottlenecks:
import "runtime/pprof"f, _ := os.Create("cpu.prof")pprof.StartCPUProfile(f)defer pprof.StopCPUProfile()// Your code here