Add a StatsBuffer circular buffer for ContainerStats.
This commit is contained in:
parent
c356d3b7c1
commit
023520da9b
56
storage/memory/stats_buffer.go
Normal file
56
storage/memory/stats_buffer.go
Normal file
@ -0,0 +1,56 @@
|
||||
package memory
|
||||
|
||||
import (
|
||||
"github.com/google/cadvisor/info"
|
||||
)
|
||||
|
||||
// A circular buffer for ContainerStats.
|
||||
type StatsBuffer struct {
|
||||
buffer []info.ContainerStats
|
||||
size int
|
||||
index int
|
||||
}
|
||||
|
||||
// Returns a new thread-compatible StatsBuffer.
|
||||
func NewStatsBuffer(size int) *StatsBuffer {
|
||||
return &StatsBuffer{
|
||||
buffer: make([]info.ContainerStats, size),
|
||||
size: 0,
|
||||
index: size - 1,
|
||||
}
|
||||
}
|
||||
|
||||
// Adds an element to the start of the buffer (removing one from the end if necessary).
|
||||
func (self *StatsBuffer) Add(item *info.ContainerStats) {
|
||||
if self.size < len(self.buffer) {
|
||||
self.size++
|
||||
}
|
||||
self.index = (self.index + 1) % len(self.buffer)
|
||||
self.buffer[self.index] = *item
|
||||
}
|
||||
|
||||
// Returns the first N elements in the buffer. If N > size of buffer, size of buffer elements are returned.
|
||||
func (self *StatsBuffer) FirstN(n int) []info.ContainerStats {
|
||||
// Cap n at the number of elements we have.
|
||||
if n > self.size {
|
||||
n = self.size
|
||||
}
|
||||
|
||||
// index points to the latest element, get n before that one (keeping in mind we may have gone through 0).
|
||||
start := self.index - (n - 1)
|
||||
if start < 0 {
|
||||
start += len(self.buffer)
|
||||
}
|
||||
|
||||
// Copy the elements.
|
||||
res := make([]info.ContainerStats, n)
|
||||
for i := 0; i < n; i++ {
|
||||
index := (start + i) % len(self.buffer)
|
||||
res[i] = self.buffer[index]
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (self *StatsBuffer) Size() int {
|
||||
return self.size
|
||||
}
|
63
storage/memory/stats_buffer_test.go
Normal file
63
storage/memory/stats_buffer_test.go
Normal file
@ -0,0 +1,63 @@
|
||||
package memory
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/cadvisor/info"
|
||||
)
|
||||
|
||||
func createStats(id int32) *info.ContainerStats {
|
||||
return &info.ContainerStats{
|
||||
Cpu: info.CpuStats{
|
||||
Load: id,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func expectSize(t *testing.T, sb *StatsBuffer, expectedSize int) {
|
||||
if sb.Size() != expectedSize {
|
||||
t.Errorf("Expected size %v, got %v", expectedSize, sb.Size())
|
||||
}
|
||||
}
|
||||
|
||||
func expectElements(t *testing.T, sb *StatsBuffer, expected []int32) {
|
||||
res := sb.FirstN(sb.Size())
|
||||
if len(res) != len(expected) {
|
||||
t.Errorf("Expected elements %v, got %v", expected, res)
|
||||
return
|
||||
}
|
||||
for i, el := range res {
|
||||
if el.Cpu.Load != expected[i] {
|
||||
t.Errorf("Expected elements %v, got %v", expected, res)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddAndFirstN(t *testing.T) {
|
||||
sb := NewStatsBuffer(5)
|
||||
|
||||
// Add 1.
|
||||
sb.Add(createStats(1))
|
||||
expectSize(t, sb, 1)
|
||||
expectElements(t, sb, []int32{1})
|
||||
|
||||
// Fill the buffer.
|
||||
for i := 1; i <= 5; i++ {
|
||||
expectSize(t, sb, i)
|
||||
sb.Add(createStats(int32(i)))
|
||||
}
|
||||
expectSize(t, sb, 5)
|
||||
expectElements(t, sb, []int32{1, 2, 3, 4, 5})
|
||||
|
||||
// Add more than is available in the buffer
|
||||
sb.Add(createStats(6))
|
||||
expectSize(t, sb, 5)
|
||||
expectElements(t, sb, []int32{2, 3, 4, 5, 6})
|
||||
|
||||
// Replace all elements.
|
||||
for i := 7; i <= 10; i++ {
|
||||
sb.Add(createStats(int32(i)))
|
||||
}
|
||||
expectSize(t, sb, 5)
|
||||
expectElements(t, sb, []int32{6, 7, 8, 9, 10})
|
||||
}
|
Loading…
Reference in New Issue
Block a user