initial import
This commit is contained in:
148
core/stat/internal/cpu_linux.go
Normal file
148
core/stat/internal/cpu_linux.go
Normal file
@@ -0,0 +1,148 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"zero/core/iox"
|
||||
"zero/core/lang"
|
||||
)
|
||||
|
||||
const (
|
||||
cpuTicks = 100
|
||||
cpuFields = 8
|
||||
)
|
||||
|
||||
var (
|
||||
preSystem uint64
|
||||
preTotal uint64
|
||||
quota float64
|
||||
cores uint64
|
||||
)
|
||||
|
||||
func init() {
|
||||
cpus, err := perCpuUsage()
|
||||
lang.Must(err)
|
||||
cores = uint64(len(cpus))
|
||||
|
||||
sets, err := cpuSets()
|
||||
lang.Must(err)
|
||||
quota = float64(len(sets))
|
||||
cq, err := cpuQuota()
|
||||
if err == nil {
|
||||
if cq != -1 {
|
||||
period, err := cpuPeriod()
|
||||
lang.Must(err)
|
||||
|
||||
limit := float64(cq) / float64(period)
|
||||
if limit < quota {
|
||||
quota = limit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
preSystem, err = systemCpuUsage()
|
||||
lang.Must(err)
|
||||
|
||||
preTotal, err = totalCpuUsage()
|
||||
lang.Must(err)
|
||||
}
|
||||
|
||||
func RefreshCpu() uint64 {
|
||||
total, err := totalCpuUsage()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
system, err := systemCpuUsage()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
var usage uint64
|
||||
cpuDelta := total - preTotal
|
||||
systemDelta := system - preSystem
|
||||
if cpuDelta > 0 && systemDelta > 0 {
|
||||
usage = uint64(float64(cpuDelta*cores*1e3) / (float64(systemDelta) * quota))
|
||||
}
|
||||
preSystem = system
|
||||
preTotal = total
|
||||
|
||||
return usage
|
||||
}
|
||||
|
||||
func cpuQuota() (int64, error) {
|
||||
cg, err := currentCgroup()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return cg.cpuQuotaUs()
|
||||
}
|
||||
|
||||
func cpuPeriod() (uint64, error) {
|
||||
cg, err := currentCgroup()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return cg.cpuPeriodUs()
|
||||
}
|
||||
|
||||
func cpuSets() ([]uint64, error) {
|
||||
cg, err := currentCgroup()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cg.cpus()
|
||||
}
|
||||
|
||||
func perCpuUsage() ([]uint64, error) {
|
||||
cg, err := currentCgroup()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cg.acctUsagePerCpu()
|
||||
}
|
||||
|
||||
func systemCpuUsage() (uint64, error) {
|
||||
lines, err := iox.ReadTextLines("/proc/stat", iox.WithoutBlank())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
for _, line := range lines {
|
||||
fields := strings.Fields(line)
|
||||
if fields[0] == "cpu" {
|
||||
if len(fields) < cpuFields {
|
||||
return 0, fmt.Errorf("bad format of cpu stats")
|
||||
}
|
||||
|
||||
var totalClockTicks uint64
|
||||
for _, i := range fields[1:cpuFields] {
|
||||
v, err := parseUint(i)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
totalClockTicks += v
|
||||
}
|
||||
|
||||
return (totalClockTicks * uint64(time.Second)) / cpuTicks, nil
|
||||
}
|
||||
}
|
||||
|
||||
return 0, errors.New("bad stats format")
|
||||
}
|
||||
|
||||
func totalCpuUsage() (usage uint64, err error) {
|
||||
var cg *cgroup
|
||||
if cg, err = currentCgroup(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return cg.acctUsageAllCpus()
|
||||
}
|
||||
Reference in New Issue
Block a user