@cryptotaxi247 / netdata-1 / commits / a862c34ad

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