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:
parent
cc658804c0
commit
2d4fc1de05
8 changed files with 30 additions and 56 deletions
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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"`
|
||||
|
|
|
@ -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"`
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Add table
Reference in a new issue