Example #1
0
def _parse_turbostat_line(heading, line):
    """Parse a single turbostat line."""

    line_data = {}
    for key, value in zip_longest(heading.keys(), line):
        if value is not None and value != "-":
            if not heading[key]:
                if Trivial.is_int(value):
                    heading[key] = int
                elif Trivial.is_float(value):
                    heading[key] = float
                else:
                    heading[key] = str
            line_data[key] = heading[key](value)

    return line_data
Example #2
0
    def set_intervals(self, intervals):
        """
        Set intervals for statistics collectors. The 'intervals' argument should be a dictionary
        with statistics collector names as keys and the collection interval as the value. This
        method should be called prior to the 'configure()' method. By default the statistics
        collectors use intervals from the 'DEFAULT_STINFO' statistics description dictionary.
        Returns a dictionary of the same structure as 'interval', but with interval values that will
        actually be used for all the statistics collectors.
        """

        # Convert intervals to strings and get rid of the trailing ".0" from the final string.
        for stname, interval in intervals.items():
            if not Trivial.is_float(interval):
                raise Error(
                    f"bad interval value '{interval}' for '{stname}' statistics"
                )
            self.stinfo[stname]["interval"] = float(interval)

        actual = {}
        for stname, stinfo in self.stinfo.items():
            if stinfo.get("interval"):
                actual[stname] = stinfo.get("interval")

        return actual
Example #3
0
    def _next(self):
        """
        Generator which yields a dictionary corresponding to one snapshot of turbostat output at a
        time.
        """

        cpus = {}
        table_started = False
        nontable = {}
        heading = totals = None

        tbl_regex = re.compile(self._cols_regex)

        for line in self._lines:
            # Ignore empty and 'jitter' lines like "turbostat: cpu65 jitter 2574 5881".
            if not line or line.startswith("turbostat: "):
                continue

            # Match the beginning of the turbostat table.
            if not table_started and not re.match(tbl_regex, line):
                _add_nontable_data(nontable, line)
                continue

            line = line.split()
            if Trivial.is_float(line[0]):
                # This is the continuation of the table we are currently parsing. It starts either
                # with a floating-point 'Time_Of_Day_Seconds' an integer 'Core' value. Each line
                # describes a single CPU.
                cpu_data = _parse_turbostat_line(heading, line)
                cpus[cpu_data["CPU"]] = cpu_data
            else:
                # This is the start of the new table.
                if cpus or table_started:
                    if not cpus:
                        # This is the the special case for single-CPU systems. Turbostat does not
                        # print the totals because there is only one CPU and totals is the the same
                        # as the CPU information.
                        cpus[0] = totals
                    yield _construct_the_result(totals, cpus, nontable)
                    nontable = {}
                    cpus = {}

                heading = {}
                for key in line:
                    if "%" in key or "Watt" in key or key in {"Time_Of_Day_Seconds", "IPC"}:
                        heading[key] = float
                    elif key in ("Package", "Core", "CPU"):
                        heading[key] = str
                    else:
                        heading[key] = None

                # The next line is total statistics across all CPUs, exept if there is only one
                # single CPU in the system.

                # False pylint warning, see issue: https://github.com/PyCQA/pylint/issues/1830
                line = next(self._lines).split() # pylint: disable=stop-iteration-return

                # On systems with a single core turbostat does not include the "Core" colum. Similar
                # to single CPU systems - the CPU column is excluded. Make sure we always have them.
                for key in ("Core", "CPU"):
                    if key not in heading:
                        heading[key] = str
                        line.append("0")

                totals = _parse_turbostat_line(heading, line)

            table_started = True

        yield _construct_the_result(totals, cpus, nontable)