|
@@ -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:
|
|
@@ -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':
|
|
@@ -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
|
|
|
|
|
@@ -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
|
|
@@ -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
|
|
@@ -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()
|
|
@@ -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
|
|
@@ -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))
|
|
@@ -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',
|
|
@@ -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)
|
|
@@ -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
|