Skip to content
This repository was archived by the owner on Oct 13, 2023. It is now read-only.

Commit bfb975a

Browse files
committed
Use condition variable to wake stats collector.
Before the collection goroutine wakes up every 1 second (as configured). This sleep interval is in case there are no stats to collect we don't end up in a tight loop. Instead use a condition variable to signal that a collection is needed. This prevents us from waking the goroutine needlessly when there is no one looking for stats. For now I've kept the sleep just moved it to the end of the loop, which gives some space between collections. Signed-off-by: Brian Goff <cpuguy83@gmail.com> (cherry picked from commit e75e6b0e31428c00047bc814746aff4b4c7c90ad) Signed-off-by: Brian Goff <cpuguy83@gmail.com> Upstream-commit: 0901d4ab31294ec3dcb01c9b224e10f9b8930dbb Component: engine
1 parent 9b30897 commit bfb975a

1 file changed

Lines changed: 15 additions & 10 deletions

File tree

components/engine/daemon/stats/collector.go

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
// Collector manages and provides container resource stats
1515
type Collector struct {
1616
m sync.Mutex
17+
cond *sync.Cond
1718
supervisor supervisor
1819
interval time.Duration
1920
publishers map[*container.Container]*pubsub.Publisher
@@ -31,6 +32,7 @@ func NewCollector(supervisor supervisor, interval time.Duration) *Collector {
3132
publishers: make(map[*container.Container]*pubsub.Publisher),
3233
bufReader: bufio.NewReaderSize(nil, 128),
3334
}
35+
s.cond = sync.NewCond(&s.m)
3436

3537
platformNewStatsCollector(s)
3638

@@ -46,13 +48,16 @@ type supervisor interface {
4648
// the event loop for collection on the specified interval returning
4749
// a channel for the subscriber to receive on.
4850
func (s *Collector) Collect(c *container.Container) chan interface{} {
49-
s.m.Lock()
50-
defer s.m.Unlock()
51+
s.cond.L.Lock()
52+
defer s.cond.L.Unlock()
53+
5154
publisher, exists := s.publishers[c]
5255
if !exists {
5356
publisher = pubsub.NewPublisher(100*time.Millisecond, 1024)
5457
s.publishers[c] = publisher
5558
}
59+
60+
s.cond.Broadcast()
5661
return publisher.Subscribe()
5762
}
5863

@@ -91,23 +96,21 @@ func (s *Collector) Run() {
9196
var pairs []publishersPair
9297

9398
for {
94-
// Put sleep at the start so that it will always be hit,
95-
// preventing a tight loop if no stats are collected.
96-
time.Sleep(s.interval)
99+
s.cond.L.Lock()
100+
for len(s.publishers) == 0 {
101+
s.cond.Wait()
102+
}
97103

98104
// it does not make sense in the first iteration,
99105
// but saves allocations in further iterations
100106
pairs = pairs[:0]
101107

102-
s.m.Lock()
103108
for container, publisher := range s.publishers {
104109
// copy pointers here to release the lock ASAP
105110
pairs = append(pairs, publishersPair{container, publisher})
106111
}
107-
s.m.Unlock()
108-
if len(pairs) == 0 {
109-
continue
110-
}
112+
113+
s.cond.L.Unlock()
111114

112115
onlineCPUs, err := s.getNumberOnlineCPUs()
113116
if err != nil {
@@ -149,6 +152,8 @@ func (s *Collector) Run() {
149152
})
150153
}
151154
}
155+
156+
time.Sleep(s.interval)
152157
}
153158
}
154159

0 commit comments

Comments
 (0)