...

Source file src/github.com/shirou/gopsutil/cpu/cpu.go

Documentation: github.com/shirou/gopsutil/cpu

     1  package cpu
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  	"math"
     8  	"strconv"
     9  	"strings"
    10  	"sync"
    11  	"time"
    12  
    13  	"github.com/shirou/gopsutil/internal/common"
    14  )
    15  
    16  // TimesStat contains the amounts of time the CPU has spent performing different
    17  // kinds of work. Time units are in seconds. It is based on linux /proc/stat file.
    18  type TimesStat struct {
    19  	CPU       string  `json:"cpu"`
    20  	User      float64 `json:"user"`
    21  	System    float64 `json:"system"`
    22  	Idle      float64 `json:"idle"`
    23  	Nice      float64 `json:"nice"`
    24  	Iowait    float64 `json:"iowait"`
    25  	Irq       float64 `json:"irq"`
    26  	Softirq   float64 `json:"softirq"`
    27  	Steal     float64 `json:"steal"`
    28  	Guest     float64 `json:"guest"`
    29  	GuestNice float64 `json:"guestNice"`
    30  }
    31  
    32  type InfoStat struct {
    33  	CPU        int32    `json:"cpu"`
    34  	VendorID   string   `json:"vendorId"`
    35  	Family     string   `json:"family"`
    36  	Model      string   `json:"model"`
    37  	Stepping   int32    `json:"stepping"`
    38  	PhysicalID string   `json:"physicalId"`
    39  	CoreID     string   `json:"coreId"`
    40  	Cores      int32    `json:"cores"`
    41  	ModelName  string   `json:"modelName"`
    42  	Mhz        float64  `json:"mhz"`
    43  	CacheSize  int32    `json:"cacheSize"`
    44  	Flags      []string `json:"flags"`
    45  	Microcode  string   `json:"microcode"`
    46  }
    47  
    48  type lastPercent struct {
    49  	sync.Mutex
    50  	lastCPUTimes    []TimesStat
    51  	lastPerCPUTimes []TimesStat
    52  }
    53  
    54  var lastCPUPercent lastPercent
    55  var invoke common.Invoker = common.Invoke{}
    56  
    57  func init() {
    58  	lastCPUPercent.Lock()
    59  	lastCPUPercent.lastCPUTimes, _ = Times(false)
    60  	lastCPUPercent.lastPerCPUTimes, _ = Times(true)
    61  	lastCPUPercent.Unlock()
    62  }
    63  
    64  // Counts returns the number of physical or logical cores in the system
    65  func Counts(logical bool) (int, error) {
    66  	return CountsWithContext(context.Background(), logical)
    67  }
    68  
    69  func (c TimesStat) String() string {
    70  	v := []string{
    71  		`"cpu":"` + c.CPU + `"`,
    72  		`"user":` + strconv.FormatFloat(c.User, 'f', 1, 64),
    73  		`"system":` + strconv.FormatFloat(c.System, 'f', 1, 64),
    74  		`"idle":` + strconv.FormatFloat(c.Idle, 'f', 1, 64),
    75  		`"nice":` + strconv.FormatFloat(c.Nice, 'f', 1, 64),
    76  		`"iowait":` + strconv.FormatFloat(c.Iowait, 'f', 1, 64),
    77  		`"irq":` + strconv.FormatFloat(c.Irq, 'f', 1, 64),
    78  		`"softirq":` + strconv.FormatFloat(c.Softirq, 'f', 1, 64),
    79  		`"steal":` + strconv.FormatFloat(c.Steal, 'f', 1, 64),
    80  		`"guest":` + strconv.FormatFloat(c.Guest, 'f', 1, 64),
    81  		`"guestNice":` + strconv.FormatFloat(c.GuestNice, 'f', 1, 64),
    82  	}
    83  
    84  	return `{` + strings.Join(v, ",") + `}`
    85  }
    86  
    87  // Total returns the total number of seconds in a CPUTimesStat
    88  func (c TimesStat) Total() float64 {
    89  	total := c.User + c.System + c.Nice + c.Iowait + c.Irq + c.Softirq +
    90  		c.Steal + c.Idle
    91  	return total
    92  }
    93  
    94  func (c InfoStat) String() string {
    95  	s, _ := json.Marshal(c)
    96  	return string(s)
    97  }
    98  
    99  func getAllBusy(t TimesStat) (float64, float64) {
   100  	busy := t.User + t.System + t.Nice + t.Iowait + t.Irq +
   101  		t.Softirq + t.Steal
   102  	return busy + t.Idle, busy
   103  }
   104  
   105  func calculateBusy(t1, t2 TimesStat) float64 {
   106  	t1All, t1Busy := getAllBusy(t1)
   107  	t2All, t2Busy := getAllBusy(t2)
   108  
   109  	if t2Busy <= t1Busy {
   110  		return 0
   111  	}
   112  	if t2All <= t1All {
   113  		return 100
   114  	}
   115  	return math.Min(100, math.Max(0, (t2Busy-t1Busy)/(t2All-t1All)*100))
   116  }
   117  
   118  func calculateAllBusy(t1, t2 []TimesStat) ([]float64, error) {
   119  	// Make sure the CPU measurements have the same length.
   120  	if len(t1) != len(t2) {
   121  		return nil, fmt.Errorf(
   122  			"received two CPU counts: %d != %d",
   123  			len(t1), len(t2),
   124  		)
   125  	}
   126  
   127  	ret := make([]float64, len(t1))
   128  	for i, t := range t2 {
   129  		ret[i] = calculateBusy(t1[i], t)
   130  	}
   131  	return ret, nil
   132  }
   133  
   134  // Percent calculates the percentage of cpu used either per CPU or combined.
   135  // If an interval of 0 is given it will compare the current cpu times against the last call.
   136  // Returns one value per cpu, or a single value if percpu is set to false.
   137  func Percent(interval time.Duration, percpu bool) ([]float64, error) {
   138  	return PercentWithContext(context.Background(), interval, percpu)
   139  }
   140  
   141  func PercentWithContext(ctx context.Context, interval time.Duration, percpu bool) ([]float64, error) {
   142  	if interval <= 0 {
   143  		return percentUsedFromLastCall(percpu)
   144  	}
   145  
   146  	// Get CPU usage at the start of the interval.
   147  	cpuTimes1, err := Times(percpu)
   148  	if err != nil {
   149  		return nil, err
   150  	}
   151  
   152  	if err := common.Sleep(ctx, interval); err != nil {
   153  		return nil, err
   154  	}
   155  
   156  	// And at the end of the interval.
   157  	cpuTimes2, err := Times(percpu)
   158  	if err != nil {
   159  		return nil, err
   160  	}
   161  
   162  	return calculateAllBusy(cpuTimes1, cpuTimes2)
   163  }
   164  
   165  func percentUsedFromLastCall(percpu bool) ([]float64, error) {
   166  	cpuTimes, err := Times(percpu)
   167  	if err != nil {
   168  		return nil, err
   169  	}
   170  	lastCPUPercent.Lock()
   171  	defer lastCPUPercent.Unlock()
   172  	var lastTimes []TimesStat
   173  	if percpu {
   174  		lastTimes = lastCPUPercent.lastPerCPUTimes
   175  		lastCPUPercent.lastPerCPUTimes = cpuTimes
   176  	} else {
   177  		lastTimes = lastCPUPercent.lastCPUTimes
   178  		lastCPUPercent.lastCPUTimes = cpuTimes
   179  	}
   180  
   181  	if lastTimes == nil {
   182  		return nil, fmt.Errorf("error getting times for cpu percent. lastTimes was nil")
   183  	}
   184  	return calculateAllBusy(lastTimes, cpuTimes)
   185  }
   186  

View as plain text