cpuidle.chart.py: only tickle known-to-be-idle CPUs
This should prevent the netdata.plugin_pythond_cpuidle metric from spiking under load. Signed-off-by: Steven Noonan <steven@uplinklabs.net>
Steven Noonan committed
Sep 10, 2017 at 14:16 UTC
a862c34ad543b483a4ae049fea4576b8df093b4d
1 file changed
+20
-6
python.d/cpuidle.chart.py
+20
-6
@@ -26,6 +26,7 @@ class Service(SimpleService):
26
self.definitions = {}
27
self._orig_name = ""
28
self.assignment = {}
29
+ self.last_schedstat = None
30
31
def __gettid(self):
32
# This is horrendous. We need the *thread id* (not the *process id*),
@@ -42,13 +43,13 @@ class Service(SimpleService):
43
tid = syscall(syscalls[platform.machine()])
44
return tid
45
45
- def __wake_cpus(self):
46
+ def __wake_cpus(self, cpus):
47
# Requires Python 3.3+. This will "tickle" each CPU to force it to
48
# update its idle counters.
49
if hasattr(os, 'sched_setaffinity'):
50
pid = self.__gettid()
51
save_affinity = os.sched_getaffinity(pid)
51
- for idx in range(0, len(self.assignment)):
52
+ for idx in cpus:
53
os.sched_setaffinity(pid, [idx])
54
os.sched_getaffinity(pid)
55
os.sched_setaffinity(pid, save_affinity)
@@ -67,14 +68,27 @@ class Service(SimpleService):
68
def _get_data(self):
69
results = {}
70
70
- # This line is critical for the stats to update. If we don't "tickle"
71
- # all the CPUs, then all the counters stop counting.
72
- self.__wake_cpus()
73
-
71
# Use the kernel scheduler stats to determine how much time was spent
72
# in C0 (active).
73
schedstat = self.__read_schedstat()
74
75
+ # Determine if any of the CPUs are idle. If they are, then we need to
76
+ # tickle them in order to update their C-state residency statistics.
77
+ if self.last_schedstat is None:
78
+ needs_tickle = list(self.assignment.keys())
79
+ else:
80
+ needs_tickle = []
81
+ for cpu, active_time in self.last_schedstat.items():
82
+ delta = schedstat[cpu] - active_time
83
+ if delta < 1:
84
+ needs_tickle.append(cpu)
85
+ self.last_schedstat = schedstat
86
+
87
+ if needs_tickle:
88
+ # This line is critical for the stats to update. If we don't "tickle"
89
+ # idle CPUs, then the counters for those CPUs stop counting.
90
+ self.__wake_cpus([int(cpu[3:]) for cpu in needs_tickle])
91
+
92
for cpu, metrics in self.assignment.items():
93
update_time = schedstat[cpu]
94
results[cpu + '_active_time'] = update_time