From 900a3f76c8e9e466b9597fe2c1d683999a418f41 Mon Sep 17 00:00:00 2001 From: Nan Deng Date: Tue, 24 Jun 2014 16:01:13 -0700 Subject: [PATCH] cpu hot plugging --- info/container.go | 24 ++++++++++----------- info/container_test.go | 47 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/info/container.go b/info/container.go index 7860c9d3..3e2447d9 100644 --- a/info/container.go +++ b/info/container.go @@ -119,7 +119,7 @@ type CpuStats struct { // Per CPU/core usage of the container. // Unit: nanoseconds. - PerCpu []uint64 `json:"per_cpu,omitempty"` + PerCpu []uint64 `json:"per_cpu_usage,omitempty"` // Time spent in user space. // Unit: nanoseconds @@ -175,7 +175,7 @@ type ContainerStatsSample struct { Usage uint64 `json:"usage"` // Per-core usage of the container. (unit: nanoseconds) - PerCpu []uint64 `json:"per_cpu,omitempty"` + PerCpuUsage []uint64 `json:"per_cpu_usage,omitempty"` } `json:"cpu"` Memory struct { // Units: Bytes. @@ -218,24 +218,24 @@ func NewSample(prev, current *ContainerStats) (*ContainerStatsSample, error) { var percpu []uint64 if len(current.Cpu.Usage.PerCpu) > 0 { - if len(current.Cpu.Usage.PerCpu) != len(prev.Cpu.Usage.PerCpu) { - return nil, fmt.Errorf("current number of cores is %v; but there are %v cores in previous stats", - len(current.Cpu.Usage.PerCpu), len(prev.Cpu.Usage.PerCpu)) - } - percpu = make([]uint64, len(current.Cpu.Usage.PerCpu)) + curNumCpus := len(current.Cpu.Usage.PerCpu) + percpu = make([]uint64, curNumCpus) - for i, curUsage := range current.Cpu.Usage.PerCpu { - prevUsage := prev.Cpu.Usage.PerCpu[i] - if curUsage < prevUsage { + for i, currUsage := range current.Cpu.Usage.PerCpu { + var prevUsage uint64 = 0 + if i < len(prev.Cpu.Usage.PerCpu) { + prevUsage = prev.Cpu.Usage.PerCpu[i] + } + if currUsage < prevUsage { return nil, fmt.Errorf("current per-core CPU usage is less than prev per-core CPU usage (cumulative).") } - percpu[i] = curUsage - prevUsage + percpu[i] = currUsage - prevUsage } } sample := new(ContainerStatsSample) // Calculate the diff to get the CPU usage within the time interval. sample.Cpu.Usage = current.Cpu.Usage.Total - prev.Cpu.Usage.Total - sample.Cpu.PerCpu = percpu + sample.Cpu.PerCpuUsage = percpu // Memory usage is current memory usage sample.Memory.Usage = current.Memory.Usage sample.Timestamp = current.Timestamp diff --git a/info/container_test.go b/info/container_test.go index 4b275bec..071ed914 100644 --- a/info/container_test.go +++ b/info/container_test.go @@ -230,3 +230,50 @@ func TestAddSampleWrongCpuUsage(t *testing.T) { t.Errorf("generated an unexpected sample: %+v", sample) } } + +func TestAddSampleHotPluggingCpu(t *testing.T) { + cpuPrevUsage := uint64(10) + cpuCurrentUsage := uint64(15) + memCurrentUsage := uint64(200) + prevTime := time.Now() + + prev := createStats(cpuPrevUsage, memCurrentUsage, prevTime) + current := createStats(cpuCurrentUsage, memCurrentUsage, prevTime.Add(1*time.Second)) + current.Cpu.Usage.PerCpu = append(current.Cpu.Usage.PerCpu, 10) + + sample, err := NewSample(prev, current) + if err != nil { + t.Errorf("should be able to generate a sample. but received error: %v", err) + } + if len(sample.Cpu.PerCpuUsage) != 2 { + t.Fatalf("Should have 2 cores.") + } + if sample.Cpu.PerCpuUsage[0] != cpuCurrentUsage-cpuPrevUsage { + t.Errorf("First cpu usage is %v. should be %v", sample.Cpu.PerCpuUsage[0], cpuCurrentUsage-cpuPrevUsage) + } + if sample.Cpu.PerCpuUsage[1] != 10 { + t.Errorf("Second cpu usage is %v. should be 10", sample.Cpu.PerCpuUsage[1]) + } +} + +func TestAddSampleHotUnpluggingCpu(t *testing.T) { + cpuPrevUsage := uint64(10) + cpuCurrentUsage := uint64(15) + memCurrentUsage := uint64(200) + prevTime := time.Now() + + prev := createStats(cpuPrevUsage, memCurrentUsage, prevTime) + current := createStats(cpuCurrentUsage, memCurrentUsage, prevTime.Add(1*time.Second)) + prev.Cpu.Usage.PerCpu = append(prev.Cpu.Usage.PerCpu, 10) + + sample, err := NewSample(prev, current) + if err != nil { + t.Errorf("should be able to generate a sample. but received error: %v", err) + } + if len(sample.Cpu.PerCpuUsage) != 1 { + t.Fatalf("Should have 1 cores.") + } + if sample.Cpu.PerCpuUsage[0] != cpuCurrentUsage-cpuPrevUsage { + t.Errorf("First cpu usage is %v. should be %v", sample.Cpu.PerCpuUsage[0], cpuCurrentUsage-cpuPrevUsage) + } +}