github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/client/stats/cpu.go (about)

     1  package stats
     2  
     3  import (
     4  	"runtime"
     5  	"time"
     6  
     7  	shelpers "github.com/hashicorp/nomad/helper/stats"
     8  	"github.com/shirou/gopsutil/cpu"
     9  )
    10  
    11  // CpuStats calculates cpu usage percentage
    12  type CpuStats struct {
    13  	prevCpuTime float64
    14  	prevTime    time.Time
    15  
    16  	totalCpus int
    17  }
    18  
    19  // NewCpuStats returns a cpu stats calculator
    20  func NewCpuStats() *CpuStats {
    21  	numCpus := runtime.NumCPU()
    22  	cpuStats := &CpuStats{
    23  		totalCpus: numCpus,
    24  	}
    25  	return cpuStats
    26  }
    27  
    28  // Percent calculates the cpu usage percentage based on the current cpu usage
    29  // and the previous cpu usage where usage is given as time in nanoseconds spend
    30  // in the cpu
    31  func (c *CpuStats) Percent(cpuTime float64) float64 {
    32  	now := time.Now()
    33  
    34  	if c.prevCpuTime == 0.0 {
    35  		// invoked first time
    36  		c.prevCpuTime = cpuTime
    37  		c.prevTime = now
    38  		return 0.0
    39  	}
    40  
    41  	timeDelta := now.Sub(c.prevTime).Nanoseconds()
    42  	ret := c.calculatePercent(c.prevCpuTime, cpuTime, timeDelta)
    43  	c.prevCpuTime = cpuTime
    44  	c.prevTime = now
    45  	return ret
    46  }
    47  
    48  // TicksConsumed calculates the total ticks consumes by the process across all
    49  // cpu cores
    50  func (c *CpuStats) TicksConsumed(percent float64) float64 {
    51  	return (percent / 100) * shelpers.TotalTicksAvailable() / float64(c.totalCpus)
    52  }
    53  
    54  func (c *CpuStats) calculatePercent(t1, t2 float64, timeDelta int64) float64 {
    55  	vDelta := t2 - t1
    56  	if timeDelta <= 0 || vDelta <= 0.0 {
    57  		return 0.0
    58  	}
    59  
    60  	overall_percent := (vDelta / float64(timeDelta)) * 100.0
    61  	return overall_percent
    62  }
    63  
    64  func (h *HostStatsCollector) collectCPUStats() (cpus []*CPUStats, totalTicks float64, err error) {
    65  
    66  	ticksConsumed := 0.0
    67  	cpuStats, err := cpu.Times(true)
    68  	if err != nil {
    69  		return nil, 0.0, err
    70  	}
    71  	cs := make([]*CPUStats, len(cpuStats))
    72  	for idx, cpuStat := range cpuStats {
    73  		percentCalculator, ok := h.statsCalculator[cpuStat.CPU]
    74  		if !ok {
    75  			percentCalculator = NewHostCpuStatsCalculator()
    76  			h.statsCalculator[cpuStat.CPU] = percentCalculator
    77  		}
    78  		idle, user, system, total := percentCalculator.Calculate(cpuStat)
    79  		cs[idx] = &CPUStats{
    80  			CPU:    cpuStat.CPU,
    81  			User:   user,
    82  			System: system,
    83  			Idle:   idle,
    84  			Total:  total,
    85  		}
    86  		ticksConsumed += (total / 100.0) * (shelpers.TotalTicksAvailable() / float64(len(cpuStats)))
    87  	}
    88  
    89  	return cs, ticksConsumed, nil
    90  }