1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Refactor usage calc for CPU and system usage

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
Michael Crosby 2015-01-19 14:07:21 -08:00
parent cc658804c0
commit 2d4fc1de05
8 changed files with 30 additions and 56 deletions

View file

@ -2717,11 +2717,16 @@ func (cli *DockerCli) CmdStats(args ...string) error {
}
func calcuateCpuPercent(previousCpu, previousSystem uint64, v *stats.Stats) float64 {
cpuPercent := 0.0
cpuDelta := float64(v.CpuStats.CpuUsage.TotalUsage) - float64(previousCpu)
systemDelta := float64(int(v.CpuStats.SystemUsage)/v.ClockTicks) - float64(int(previousSystem)/v.ClockTicks)
if systemDelta > 0.0 {
cpuPercent = (cpuDelta / systemDelta) * float64(v.ClockTicks*len(v.CpuStats.CpuUsage.PercpuUsage))
var (
cpuPercent = 0.0
// calculate the change for the cpu usage of the container in between readings
cpuDelta = float64(v.CpuStats.CpuUsage.TotalUsage - previousCpu)
// calculate the change for the entire system between readings
systemDelta = float64(v.CpuStats.SystemUsage - previousSystem)
)
if systemDelta > 0.0 && cpuDelta > 0.0 {
cpuPercent = (cpuDelta / systemDelta) * float64(len(v.CpuStats.CpuUsage.PercpuUsage)) * 100.0
}
return cpuPercent
}

View file

@ -1,29 +0,0 @@
package client
import "sort"
func sortStatsByName(cStats map[string]containerStats) []containerStats {
sStats := []containerStats{}
for _, s := range cStats {
sStats = append(sStats, s)
}
sorter := &statSorter{sStats}
sort.Sort(sorter)
return sStats
}
type statSorter struct {
stats []containerStats
}
func (s *statSorter) Len() int {
return len(s.stats)
}
func (s *statSorter) Swap(i, j int) {
s.stats[i], s.stats[j] = s.stats[j], s.stats[i]
}
func (s *statSorter) Less(i, j int) bool {
return s.stats[i].Name < s.stats[j].Name
}

View file

@ -83,8 +83,6 @@ type Network struct {
type Stats struct {
Read time.Time `json:"read"`
ClockTicks int `json:"clock_ticks"`
Interval int `json:"interval"` // in ms
Network Network `json:"network,omitempty"`
CpuStats CpuStats `json:"cpu_stats,omitempty"`
MemoryStats MemoryStats `json:"memory_stats,omitempty"`

View file

@ -107,7 +107,6 @@ type Resources struct {
type ResourceStats struct {
*libcontainer.ContainerStats
Read time.Time `json:"read"`
ClockTicks int `json:"clock_ticks"`
MemoryLimit int64 `json:"memory_limit"`
SystemUsage uint64 `json:"system_usage"`
}

View file

@ -8,15 +8,9 @@ import (
"github.com/docker/docker/daemon/execdriver/lxc"
"github.com/docker/docker/daemon/execdriver/native"
"github.com/docker/docker/pkg/sysinfo"
"github.com/docker/docker/pkg/system"
)
func NewDriver(name, root, initPath string, sysInfo *sysinfo.SysInfo) (execdriver.Driver, error) {
meminfo, err := system.ReadMemInfo()
if err != nil {
return nil, err
}
switch name {
case "lxc":
// we want to give the lxc driver the full docker root because it needs
@ -24,7 +18,7 @@ func NewDriver(name, root, initPath string, sysInfo *sysinfo.SysInfo) (execdrive
// to be backwards compatible
return lxc.NewDriver(root, initPath, sysInfo.AppArmor)
case "native":
return native.NewDriver(path.Join(root, "execdriver", "native"), initPath, meminfo.MemTotal)
return native.NewDriver(path.Join(root, "execdriver", "native"), initPath)
}
return nil, fmt.Errorf("unknown exec driver %s", name)
}

View file

@ -17,6 +17,7 @@ import (
log "github.com/Sirupsen/logrus"
"github.com/docker/docker/daemon/execdriver"
sysinfo "github.com/docker/docker/pkg/system"
"github.com/docker/docker/pkg/term"
"github.com/docker/libcontainer"
"github.com/docker/libcontainer/apparmor"
@ -46,7 +47,12 @@ type driver struct {
sync.Mutex
}
func NewDriver(root, initPath string, machineMemory int64) (*driver, error) {
func NewDriver(root, initPath string) (*driver, error) {
meminfo, err := sysinfo.ReadMemInfo()
if err != nil {
return nil, err
}
if err := os.MkdirAll(root, 0700); err != nil {
return nil, err
}
@ -58,7 +64,7 @@ func NewDriver(root, initPath string, machineMemory int64) (*driver, error) {
root: root,
initPath: initPath,
activeContainers: make(map[string]*activeContainer),
machineMemory: machineMemory,
machineMemory: meminfo.MemTotal,
}, nil
}
@ -303,7 +309,6 @@ func (d *driver) Stats(id string) (*execdriver.ResourceStats, error) {
return &execdriver.ResourceStats{
Read: now,
ContainerStats: stats,
ClockTicks: system.GetClockTicks(),
MemoryLimit: memoryLimit,
}, nil
}

View file

@ -17,7 +17,6 @@ func (daemon *Daemon) ContainerStats(job *engine.Job) engine.Status {
ss := stats.ToStats(update.ContainerStats)
ss.MemoryStats.Limit = uint64(update.MemoryLimit)
ss.Read = update.Read
ss.ClockTicks = update.ClockTicks
ss.CpuStats.SystemUsage = update.SystemUsage
if err := enc.Encode(ss); err != nil {
// TODO: handle the specific broken pipe

View file

@ -11,6 +11,7 @@ import (
log "github.com/Sirupsen/logrus"
"github.com/docker/docker/daemon/execdriver"
"github.com/docker/libcontainer/system"
)
// newStatsCollector returns a new statsCollector that collections
@ -21,6 +22,7 @@ func newStatsCollector(interval time.Duration) *statsCollector {
s := &statsCollector{
interval: interval,
containers: make(map[string]*statsData),
clockTicks: uint64(system.GetClockTicks()),
}
s.start()
return s
@ -36,6 +38,7 @@ type statsData struct {
type statsCollector struct {
m sync.Mutex
interval time.Duration
clockTicks uint64
containers map[string]*statsData
}
@ -128,8 +131,10 @@ func (s *statsCollector) start() {
}()
}
// getSystemdCpuUSage returns the host system's cpu usage
// in nanoseconds.
const nanoSeconds = 1e9
// getSystemdCpuUSage returns the host system's cpu usage in nanoseconds
// for the system to match the cgroup readings are returned in the same format.
func (s *statsCollector) getSystemCpuUsage() (uint64, error) {
f, err := os.Open("/proc/stat")
if err != nil {
@ -144,17 +149,15 @@ func (s *statsCollector) getSystemCpuUsage() (uint64, error) {
if len(parts) < 8 {
return 0, fmt.Errorf("invalid number of cpu fields")
}
var total uint64
var sum uint64
for _, i := range parts[1:8] {
v, err := strconv.ParseUint(i, 10, 64)
if err != nil {
return 0.0, fmt.Errorf("Unable to convert value %s to int: %s", i, err)
return 0, fmt.Errorf("Unable to convert value %s to int: %s", i, err)
}
total += v
sum += v
}
return total * 1000000000, nil
default:
continue
return (sum * nanoSeconds) / s.clockTicks, nil
}
}
return 0, fmt.Errorf("invalid stat format")