2023-04-10 15:36:59 +00:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
2016-06-10 21:46:33 +00:00
|
|
|
package stats
|
|
|
|
|
|
|
|
import (
|
2023-07-19 18:31:14 +00:00
|
|
|
"runtime"
|
2018-05-08 21:00:31 +00:00
|
|
|
"time"
|
2023-03-28 13:27:58 +00:00
|
|
|
)
|
2016-06-17 19:13:53 +00:00
|
|
|
|
2023-03-28 13:27:58 +00:00
|
|
|
var (
|
2023-07-19 18:31:14 +00:00
|
|
|
cpuTotalTicks uint64
|
2016-06-10 21:46:33 +00:00
|
|
|
)
|
|
|
|
|
2023-07-19 18:31:14 +00:00
|
|
|
// CpuStats calculates cpu usage percentage
|
|
|
|
type CpuStats struct {
|
|
|
|
prevCpuTime float64
|
|
|
|
prevTime time.Time
|
2023-03-28 13:27:58 +00:00
|
|
|
|
2023-07-19 18:31:14 +00:00
|
|
|
totalCpus int
|
|
|
|
}
|
2017-06-27 18:54:15 +00:00
|
|
|
|
2023-07-19 18:31:14 +00:00
|
|
|
// NewCpuStats returns a cpu stats calculator
|
|
|
|
func NewCpuStats() *CpuStats {
|
|
|
|
numCpus := runtime.NumCPU()
|
|
|
|
cpuStats := &CpuStats{
|
|
|
|
totalCpus: numCpus,
|
|
|
|
}
|
|
|
|
return cpuStats
|
|
|
|
}
|
2023-03-28 13:27:58 +00:00
|
|
|
|
2023-07-19 18:31:14 +00:00
|
|
|
// Percent calculates the cpu usage percentage based on the current cpu usage
|
|
|
|
// and the previous cpu usage where usage is given as time in nanoseconds spend
|
|
|
|
// in the cpu
|
|
|
|
func (c *CpuStats) Percent(cpuTime float64) float64 {
|
|
|
|
now := time.Now()
|
|
|
|
|
|
|
|
if c.prevCpuTime == 0.0 {
|
|
|
|
// invoked first time
|
|
|
|
c.prevCpuTime = cpuTime
|
|
|
|
c.prevTime = now
|
|
|
|
return 0.0
|
|
|
|
}
|
|
|
|
|
|
|
|
timeDelta := now.Sub(c.prevTime).Nanoseconds()
|
|
|
|
ret := c.calculatePercent(c.prevCpuTime, cpuTime, timeDelta)
|
|
|
|
c.prevCpuTime = cpuTime
|
|
|
|
c.prevTime = now
|
|
|
|
return ret
|
2016-06-17 19:13:53 +00:00
|
|
|
}
|
|
|
|
|
2023-07-19 18:31:14 +00:00
|
|
|
// TicksConsumed calculates the total ticks consumes by the process across all
|
|
|
|
// cpu cores
|
|
|
|
func (c *CpuStats) TicksConsumed(percent float64) float64 {
|
|
|
|
return (percent / 100) * float64(CpuTotalTicks()) / float64(c.totalCpus)
|
2016-06-17 19:13:53 +00:00
|
|
|
}
|
|
|
|
|
2023-07-19 18:31:14 +00:00
|
|
|
func (c *CpuStats) calculatePercent(t1, t2 float64, timeDelta int64) float64 {
|
|
|
|
vDelta := t2 - t1
|
|
|
|
if timeDelta <= 0 || vDelta <= 0.0 {
|
|
|
|
return 0.0
|
|
|
|
}
|
|
|
|
|
|
|
|
overall_percent := (vDelta / float64(timeDelta)) * 100.0
|
|
|
|
return overall_percent
|
2016-06-17 19:13:53 +00:00
|
|
|
}
|
|
|
|
|
2023-07-19 18:31:14 +00:00
|
|
|
// Set the total ticks available across all cores.
|
|
|
|
func SetCpuTotalTicks(newCpuTotalTicks uint64) {
|
|
|
|
cpuTotalTicks = newCpuTotalTicks
|
2016-06-17 19:13:53 +00:00
|
|
|
}
|
|
|
|
|
2023-07-19 18:31:14 +00:00
|
|
|
// CpuTotalTicks calculates the total MHz available across all cores.
|
2023-03-28 13:27:58 +00:00
|
|
|
//
|
|
|
|
// Where asymetric cores are correctly detected, the total ticks is the sum of
|
|
|
|
// the performance across both core types.
|
|
|
|
//
|
|
|
|
// Where asymetric cores are not correctly detected (such as Intel 13th gen),
|
|
|
|
// the total ticks available is over-estimated, as we assume all cores are P
|
|
|
|
// cores.
|
2023-07-19 18:31:14 +00:00
|
|
|
func CpuTotalTicks() uint64 {
|
2016-06-17 19:13:53 +00:00
|
|
|
return cpuTotalTicks
|
2016-06-10 21:46:33 +00:00
|
|
|
}
|