summaryrefslogtreecommitdiffstats
path: root/python.d/cpuidle.chart.py
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2018-11-07 12:22:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2018-11-07 12:22:44 +0000
commit1e6c93250172946eeb38e94a92a1fd12c9d3011e (patch)
tree8ca5e16dfc7ad6b3bf2738ca0a48408a950f8f7e /python.d/cpuidle.chart.py
parentUpdate watch file (diff)
downloadnetdata-1e6c93250172946eeb38e94a92a1fd12c9d3011e.tar.xz
netdata-1e6c93250172946eeb38e94a92a1fd12c9d3011e.zip
Merging upstream version 1.11.0+dfsg.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'python.d/cpuidle.chart.py')
-rw-r--r--python.d/cpuidle.chart.py148
1 files changed, 0 insertions, 148 deletions
diff --git a/python.d/cpuidle.chart.py b/python.d/cpuidle.chart.py
deleted file mode 100644
index d14c6aaf..00000000
--- a/python.d/cpuidle.chart.py
+++ /dev/null
@@ -1,148 +0,0 @@
-# -*- coding: utf-8 -*-
-# Description: cpuidle netdata python.d module
-# Author: Steven Noonan (tycho)
-
-import glob
-import os
-import platform
-
-from bases.FrameworkServices.SimpleService import SimpleService
-
-import ctypes
-syscall = ctypes.CDLL('libc.so.6').syscall
-
-# default module values (can be overridden per job in `config`)
-# update_every = 2
-
-
-class Service(SimpleService):
- def __init__(self, configuration=None, name=None):
- prefix = os.getenv('NETDATA_HOST_PREFIX', "")
- if prefix.endswith('/'):
- prefix = prefix[:-1]
- self.sys_dir = prefix + "/sys/devices/system/cpu"
- self.schedstat_path = prefix + "/proc/schedstat"
- SimpleService.__init__(self, configuration=configuration, name=name)
- self.order = []
- self.definitions = {}
- self.fake_name = 'cpu'
- self.assignment = {}
- self.last_schedstat = None
-
- @staticmethod
- def __gettid():
- # This is horrendous. We need the *thread id* (not the *process id*),
- # but there's no Python standard library way of doing that. If you need
- # to enable this module on a non-x86 machine type, you'll have to find
- # the Linux syscall number for gettid() and add it to the dictionary
- # below.
- syscalls = {
- 'i386': 224,
- 'x86_64': 186,
- }
- if platform.machine() not in syscalls:
- return None
- tid = syscall(syscalls[platform.machine()])
- return tid
-
- def __wake_cpus(self, cpus):
- # Requires Python 3.3+. This will "tickle" each CPU to force it to
- # update its idle counters.
- if hasattr(os, 'sched_setaffinity'):
- pid = self.__gettid()
- save_affinity = os.sched_getaffinity(pid)
- for idx in cpus:
- os.sched_setaffinity(pid, [idx])
- os.sched_getaffinity(pid)
- os.sched_setaffinity(pid, save_affinity)
-
- def __read_schedstat(self):
- cpus = {}
- for line in open(self.schedstat_path, 'r'):
- if not line.startswith('cpu'):
- continue
- line = line.rstrip().split()
- cpu = line[0]
- active_time = line[7]
- cpus[cpu] = int(active_time) // 1000
- return cpus
-
- def _get_data(self):
- results = {}
-
- # Use the kernel scheduler stats to determine how much time was spent
- # in C0 (active).
- schedstat = self.__read_schedstat()
-
- # Determine if any of the CPUs are idle. If they are, then we need to
- # tickle them in order to update their C-state residency statistics.
- if self.last_schedstat is None:
- needs_tickle = list(self.assignment.keys())
- else:
- needs_tickle = []
- for cpu, active_time in self.last_schedstat.items():
- delta = schedstat[cpu] - active_time
- if delta < 1:
- needs_tickle.append(cpu)
-
- if needs_tickle:
- # This line is critical for the stats to update. If we don't "tickle"
- # idle CPUs, then the counters for those CPUs stop counting.
- self.__wake_cpus([int(cpu[3:]) for cpu in needs_tickle])
-
- # Re-read schedstat now that we've tickled any idlers.
- schedstat = self.__read_schedstat()
-
- self.last_schedstat = schedstat
-
- for cpu, metrics in self.assignment.items():
- update_time = schedstat[cpu]
- results[cpu + '_active_time'] = update_time
-
- for metric, path in metrics.items():
- residency = int(open(path, 'r').read())
- results[metric] = residency
-
- return results
-
- def check(self):
- if self.__gettid() is None:
- self.error("Cannot get thread ID. Stats would be completely broken.")
- return False
-
- for path in sorted(glob.glob(self.sys_dir + '/cpu*/cpuidle/state*/name')):
- # ['', 'sys', 'devices', 'system', 'cpu', 'cpu0', 'cpuidle', 'state3', 'name']
- path_elem = path.split('/')
- cpu = path_elem[-4]
- state = path_elem[-2]
- statename = open(path, 'rt').read().rstrip()
-
- orderid = '%s_cpuidle' % (cpu,)
- if orderid not in self.definitions:
- self.order.append(orderid)
- active_name = '%s_active_time' % (cpu,)
- self.definitions[orderid] = {
- 'options': [None, 'C-state residency', 'time%', 'cpuidle', 'cpuidle.cpuidle', 'stacked'],
- 'lines': [
- [active_name, 'C0 (active)', 'percentage-of-incremental-row', 1, 1],
- ],
- }
- self.assignment[cpu] = {}
-
- defid = '%s_%s_time' % (orderid, state)
-
- self.definitions[orderid]['lines'].append(
- [defid, statename, 'percentage-of-incremental-row', 1, 1]
- )
-
- self.assignment[cpu][defid] = '/'.join(path_elem[:-1] + ['time'])
-
- # Sort order by kernel-specified CPU index
- self.order.sort(key=lambda x: int(x.split('_')[0][3:]))
-
- if len(self.definitions) == 0:
- self.error("couldn't find cstate stats")
- return False
-
- return True
-