go-common/library/stat/sys/cpu/cpu.go
2019-04-22 18:49:16 +08:00

111 lines
2.0 KiB
Go

package cpu
import (
"fmt"
"go-common/library/log"
"sync/atomic"
"time"
)
var (
cores uint64
maxFreq uint64
quota float64
usage uint64
preSystem uint64
preTotal uint64
)
func init() {
cpus, err := perCPUUsage()
if err != nil {
panic(fmt.Errorf("stat/sys/cpu: perCPUUsage() failed!err:=%v", err))
}
cores = uint64(len(cpus))
sets, err := cpuSets()
if err != nil {
panic(fmt.Errorf("stat/sys/cpu: cpuSets() failed!err:=%v", err))
}
quota = float64(len(sets))
cq, err := cpuQuota()
if err == nil {
if cq != -1 {
var period uint64
if period, err = cpuPeriod(); err != nil {
panic(fmt.Errorf("stat/sys/cpu: cpuPeriod() failed!err:=%v", err))
}
limit := float64(cq) / float64(period)
if limit < quota {
quota = limit
}
}
}
maxFreq = cpuMaxFreq()
preSystem, err = systemCPUUsage()
if err != nil {
panic(fmt.Errorf("sys/cpu: systemCPUUsage() failed!err:=%v", err))
}
preTotal, err = totalCPUUsage()
if err != nil {
panic(fmt.Errorf("sys/cpu: totalCPUUsage() failed!err:=%v", err))
}
go func() {
ticker := time.NewTicker(time.Millisecond * 250)
defer ticker.Stop()
for {
<-ticker.C
cpu := refreshCPU()
if cpu != 0 {
atomic.StoreUint64(&usage, cpu)
}
}
}()
}
func refreshCPU() (u uint64) {
total, err := totalCPUUsage()
if err != nil {
log.Warn("os/stat: get totalCPUUsage failed,error(%v)", err)
return
}
system, err := systemCPUUsage()
if err != nil {
log.Warn("os/stat: get systemCPUUsage failed,error(%v)", err)
return
}
if system != preSystem {
u = uint64(float64((total-preTotal)*cores*1e3) / (float64(system-preSystem) * quota))
}
preSystem = system
preTotal = total
return u
}
// Stat cpu stat.
type Stat struct {
Usage uint64 // cpu use ratio.
}
// Info cpu info.
type Info struct {
Frequency uint64
Quota float64
}
// ReadStat read cpu stat.
func ReadStat(stat *Stat) {
stat.Usage = atomic.LoadUint64(&usage)
}
// GetInfo get cpu info.
func GetInfo() Info {
return Info{
Frequency: maxFreq,
Quota: quota,
}
}