Skip to content

Commit

Permalink
tools/kvm_stat: add new interactive command 'b'
Browse files Browse the repository at this point in the history
Toggle display total number of events by guest (debugfs only).
When switching to display of events by guest, field filters remain
active. I.e. the number of events per guest reported considers only
events matching the filters. Likewise with pid/guest filtering.
Note that when switching to display of events by guest, DebugfsProvider
remains to collect data for events as it did before, but the read()
method summarizes the values by pid.

Signed-off-by: Stefan Raspl <[email protected]>
Signed-off-by: Paolo Bonzini <[email protected]>
  • Loading branch information
Stefan Raspl authored and bonzini committed Jun 27, 2017
1 parent ab7ef19 commit 5c1954d
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 10 deletions.
87 changes: 77 additions & 10 deletions tools/kvm/kvm_stat/kvm_stat
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,7 @@ class TracepointProvider(Provider):
self.setup_traces()
self.fields = self._fields

def read(self):
def read(self, by_guest=0):
"""Returns 'event name: current value' for all enabled events."""
ret = defaultdict(int)
for group in self.group_leaders:
Expand Down Expand Up @@ -731,7 +731,7 @@ class DebugfsProvider(Provider):
self.do_read = True
self.reset()

def read(self, reset=0):
def read(self, reset=0, by_guest=0):
"""Returns a dict with format:'file name / field -> current value'.
Parameter 'reset':
Expand Down Expand Up @@ -762,8 +762,16 @@ class DebugfsProvider(Provider):
self._baseline[key] = 0
if self._baseline.get(key, -1) == -1:
self._baseline[key] = value
results[field] = (results.get(field, 0) + value -
self._baseline.get(key, 0))
increment = (results.get(field, 0) + value -
self._baseline.get(key, 0))
if by_guest:
pid = key.split('-')[0]
if pid in results:
results[pid] += increment
else:
results[pid] = increment
else:
results[field] = increment

return results

Expand Down Expand Up @@ -849,18 +857,44 @@ class Stats(object):
for provider in self.providers:
provider.pid = self._pid_filter

def get(self):
def get(self, by_guest=0):
"""Returns a dict with field -> (value, delta to last value) of all
provider data."""
for provider in self.providers:
new = provider.read()
for key in provider.fields:
new = provider.read(by_guest=by_guest)
for key in new if by_guest else provider.fields:
oldval = self.values.get(key, (0, 0))[0]
newval = new.get(key, 0)
newdelta = newval - oldval
self.values[key] = (newval, newdelta)
return self.values

def toggle_display_guests(self, to_pid):
"""Toggle between collection of stats by individual event and by
guest pid
Events reported by DebugfsProvider change when switching to/from
reading by guest values. Hence we have to remove the excess event
names from self.values.
"""
if any(isinstance(ins, TracepointProvider) for ins in self.providers):
return 1
if to_pid:
for provider in self.providers:
if isinstance(provider, DebugfsProvider):
for key in provider.fields:
if key in self.values.keys():
del self.values[key]
else:
oldvals = self.values.copy()
for key in oldvals:
if key.isdigit():
del self.values[key]
# Update oldval (see get())
self.get(to_pid)
return 0

DELAY_DEFAULT = 3.0
MAX_GUEST_NAME_LEN = 48
MAX_REGEX_LEN = 44
Expand All @@ -876,6 +910,7 @@ class Tui(object):
self._delay_initial = 0.25
self._delay_regular = DELAY_DEFAULT
self._sorting = SORT_DEFAULT
self._display_guests = 0

def __enter__(self):
"""Initialises curses for later use. Based on curses.wrapper
Expand Down Expand Up @@ -1024,8 +1059,12 @@ class Tui(object):
if len(regex) > MAX_REGEX_LEN:
regex = regex[:MAX_REGEX_LEN] + '...'
self.screen.addstr(1, 17, 'regex filter: {0}'.format(regex))
if self._display_guests:
col_name = 'Guest Name'
else:
col_name = 'Event'
self.screen.addstr(2, 1, '%-40s %10s%7s %8s' %
('Event', 'Total', '%Total', 'CurAvg/s'),
(col_name, 'Total', '%Total', 'CurAvg/s'),
curses.A_STANDOUT)
self.screen.addstr(4, 1, 'Collecting data...')
self.screen.refresh()
Expand All @@ -1034,7 +1073,7 @@ class Tui(object):
row = 3
self.screen.move(row, 0)
self.screen.clrtobot()
stats = self.stats.get()
stats = self.stats.get(self._display_guests)

def sortCurAvg(x):
# sort by current events if available
Expand Down Expand Up @@ -1062,6 +1101,8 @@ class Tui(object):
break
if values[0] is not None:
cur = int(round(values[1] / sleeptime)) if values[1] else ''
if self._display_guests:
key = self.get_gname_from_pid(key)
self.screen.addstr(row, 1, '%-40s %10d%7.1f %8s' %
(key, values[0], values[0] * 100 / total,
cur))
Expand All @@ -1070,9 +1111,26 @@ class Tui(object):
self.screen.addstr(4, 1, 'No matching events reported yet')
self.screen.refresh()

def show_msg(self, text):
"""Display message centered text and exit on key press"""
hint = 'Press any key to continue'
curses.cbreak()
self.screen.erase()
(x, term_width) = self.screen.getmaxyx()
row = 2
for line in text:
start = (term_width - len(line)) / 2
self.screen.addstr(row, start, line)
row += 1
self.screen.addstr(row + 1, (term_width - len(hint)) / 2, hint,
curses.A_STANDOUT)
self.screen.getkey()

def show_help_interactive(self):
"""Display help with list of interactive commands"""
msg = (' c clear filter',
msg = (' b toggle events by guests (debugfs only, honors'
' filters)',
' c clear filter',
' f filter by regular expression',
' g filter by guest name',
' h display interactive commands reference',
Expand Down Expand Up @@ -1253,6 +1311,14 @@ class Tui(object):
sleeptime = self._delay_regular
try:
char = self.screen.getkey()
if char == 'b':
self._display_guests = not self._display_guests
if self.stats.toggle_display_guests(self._display_guests):
self.show_msg(['Command not available with tracepoints'
' enabled', 'Restart with debugfs only '
'(see option \'-d\') and try again!'])
self._display_guests = not self._display_guests
self.refresh_header()
if char == 'c':
self.stats.fields_filter = DEFAULT_REGEX
self.refresh_header(0)
Expand Down Expand Up @@ -1356,6 +1422,7 @@ Requirements:
the large number of files that are possibly opened.
Interactive Commands:
b toggle events by guests (debugfs only, honors filters)
c clear filter
f filter by regular expression
g filter by guest name
Expand Down
2 changes: 2 additions & 0 deletions tools/kvm/kvm_stat/kvm_stat.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ meaning of events.
INTERACTIVE COMMANDS
--------------------
[horizontal]
*b*:: toggle events by guests (debugfs only, honors filters)

*c*:: clear filter

*f*:: filter by regular expression
Expand Down

0 comments on commit 5c1954d

Please sign in to comment.