Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9f114a03 authored by Stefan Raspl's avatar Stefan Raspl Committed by Paolo Bonzini
Browse files

tools/kvm_stat: add interactive command 'r'



Provide an interactive command to reset the tracepoint statistics.
Requires some extra work for debugfs, as the counters cannot be reset.

On the up side, this offers us the opportunity to have debugfs values
reset on startup and whenever a filter is modified, becoming consistent
with the tracepoint provider. As a bonus, 'kvmstat -dt' will now provide
useful output, instead of mixing values in totally different orders of
magnitude.
Furthermore, we avoid unnecessary resets when any of the filters is
"changed" interactively to the previous value.

Signed-off-by: default avatarStefan Raspl <raspl@linux.vnet.ibm.com>
Acked-by: default avatarJanosch Frank <frankja@linux.vnet.ibm.com>
Signed-off-by: default avatarRadim Krčmář <rkrcmar@redhat.com>
parent 4443084f
Loading
Loading
Loading
Loading
+51 −14
Original line number Diff line number Diff line
@@ -716,15 +716,23 @@ class TracepointProvider(object):
                    ret[name] += val
        return ret

    def reset(self):
        """Reset all field counters"""
        for group in self.group_leaders:
            for event in group.events:
                event.reset()


class DebugfsProvider(object):
    """Provides data from the files that KVM creates in the kvm debugfs
    folder."""
    def __init__(self):
        self._fields = self.get_available_fields()
        self._baseline = {}
        self._pid = 0
        self.do_read = True
        self.paths = []
        self.reset()

    def get_available_fields(self):
        """"Returns a list of available fields.
@@ -741,6 +749,7 @@ class DebugfsProvider(object):
    @fields.setter
    def fields(self, fields):
        self._fields = fields
        self.reset()

    @property
    def pid(self):
@@ -758,10 +767,11 @@ class DebugfsProvider(object):
            self.paths = filter(lambda x: "{}-".format(pid) in x, vms)

        else:
            self.paths = ['']
            self.paths = []
            self.do_read = True
        self.reset()

    def read(self):
    def read(self, reset=0):
        """Returns a dict with format:'file name / field -> current value'."""
        results = {}

@@ -769,10 +779,22 @@ class DebugfsProvider(object):
        if not self.do_read:
            return results

        for path in self.paths:
        paths = self.paths
        if self._pid == 0:
            paths = []
            for entry in os.walk(PATH_DEBUGFS_KVM):
                for dir in entry[1]:
                    paths.append(dir)
        for path in paths:
            for field in self._fields:
                results[field] = results.get(field, 0) \
                                 + self.read_field(field, path)
                value = self.read_field(field, path)
                key = path + field
                if reset:
                    self._baseline[key] = value
                if self._baseline.get(key, -1) == -1:
                    self._baseline[key] = value
                results[field] = (results.get(field, 0) + value -
                                  self._baseline.get(key, 0))

        return results

@@ -786,6 +808,11 @@ class DebugfsProvider(object):
        except IOError:
            return 0

    def reset(self):
        """Reset field counters"""
        self._baseline = {}
        self.read(1)


class Stats(object):
    """Manages the data providers and the data they provide.
@@ -822,12 +849,18 @@ class Stats(object):
        for provider in self.providers:
            provider.pid = self._pid_filter

    def reset(self):
        self.values = {}
        for provider in self.providers:
            provider.reset()

    @property
    def fields_filter(self):
        return self._fields_filter

    @fields_filter.setter
    def fields_filter(self, fields_filter):
        if fields_filter != self._fields_filter:
            self._fields_filter = fields_filter
            self.update_provider_filters()

@@ -837,6 +870,7 @@ class Stats(object):

    @pid_filter.setter
    def pid_filter(self, pid):
        if pid != self._pid_filter:
            self._pid_filter = pid
            self.values = {}
            self.update_provider_pid()
@@ -847,11 +881,9 @@ class Stats(object):
        for provider in self.providers:
            new = provider.read()
            for key in provider.fields:
                oldval = self.values.get(key, (0, 0))
                oldval = self.values.get(key, (0, 0))[0]
                newval = new.get(key, 0)
                newdelta = None
                if oldval is not None:
                    newdelta = newval - oldval[0]
                newdelta = newval - oldval
                self.values[key] = (newval, newdelta)
        return self.values

@@ -1117,6 +1149,10 @@ class Tui(object):
                if char == 'p':
                    self.show_vm_selection_by_pid()
                    sleeptime = DELAY_INITIAL
                if char == 'r':
                    self.refresh_header()
                    self.stats.reset()
                    sleeptime = DELAY_INITIAL
            except KeyboardInterrupt:
                break
            except curses.error:
@@ -1190,6 +1226,7 @@ Interactive Commands:
   p     filter by PID
   q     quit
   x     toggle reporting of stats for individual child trace events
   r     reset stats
Press any other key to refresh statistics immediately.
"""

+2 −0
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@ INTERACTIVE COMMANDS

*q*::	quit

*r*::	reset stats

*x*::	toggle reporting of stats for child trace events

Press any other key to refresh statistics immediately.