|
|
9bac43 |
From 17165a0bc8b8496f52f9273fe4466797f3a6726e Mon Sep 17 00:00:00 2001
|
|
|
9bac43 |
From: David Hildenbrand <david@redhat.com>
|
|
|
9bac43 |
Date: Tue, 17 Oct 2017 19:16:03 +0200
|
|
|
9bac43 |
Subject: [PATCH 58/69] tools/kvm_stat: add new interactive command 'b'
|
|
|
9bac43 |
|
|
|
9bac43 |
RH-Author: David Hildenbrand <david@redhat.com>
|
|
|
9bac43 |
Message-id: <20171017191605.2378-38-david@redhat.com>
|
|
|
9bac43 |
Patchwork-id: 77344
|
|
|
9bac43 |
O-Subject: [RHEL-7.5 qemu-kvm-rhev PATCH 37/39] tools/kvm_stat: add new interactive command 'b'
|
|
|
9bac43 |
Bugzilla: 1497137
|
|
|
9bac43 |
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
9bac43 |
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
|
|
|
9bac43 |
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
9bac43 |
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
|
|
9bac43 |
|
|
|
9bac43 |
Upstream-status: linux.git 5c1954d25d1b9e857be2a4c77437312075875589
|
|
|
9bac43 |
|
|
|
9bac43 |
Convertion of documentation (for man page generation) to texi.
|
|
|
9bac43 |
|
|
|
9bac43 |
commit 5c1954d25d1b9e857be2a4c77437312075875589
|
|
|
9bac43 |
Author: Stefan Raspl <raspl@linux.vnet.ibm.com>
|
|
|
9bac43 |
Date: Sun Jun 25 21:34:16 2017 +0200
|
|
|
9bac43 |
|
|
|
9bac43 |
tools/kvm_stat: add new interactive command 'b'
|
|
|
9bac43 |
|
|
|
9bac43 |
Toggle display total number of events by guest (debugfs only).
|
|
|
9bac43 |
When switching to display of events by guest, field filters remain
|
|
|
9bac43 |
active. I.e. the number of events per guest reported considers only
|
|
|
9bac43 |
events matching the filters. Likewise with pid/guest filtering.
|
|
|
9bac43 |
Note that when switching to display of events by guest, DebugfsProvider
|
|
|
9bac43 |
remains to collect data for events as it did before, but the read()
|
|
|
9bac43 |
method summarizes the values by pid.
|
|
|
9bac43 |
|
|
|
9bac43 |
Signed-off-by: Stefan Raspl <raspl@linux.vnet.ibm.com>
|
|
|
9bac43 |
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
9bac43 |
|
|
|
9bac43 |
Signed-off-by: David Hildenbrand <david@redhat.com>
|
|
|
9bac43 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
9bac43 |
---
|
|
|
9bac43 |
scripts/kvm/kvm_stat | 87 +++++++++++++++++++++++++++++++++++++++++------
|
|
|
9bac43 |
scripts/kvm/kvm_stat.texi | 3 ++
|
|
|
9bac43 |
2 files changed, 80 insertions(+), 10 deletions(-)
|
|
|
9bac43 |
|
|
|
9bac43 |
diff --git a/scripts/kvm/kvm_stat b/scripts/kvm/kvm_stat
|
|
|
9bac43 |
index 4065b29..dd8f00c 100755
|
|
|
9bac43 |
--- a/scripts/kvm/kvm_stat
|
|
|
9bac43 |
+++ b/scripts/kvm/kvm_stat
|
|
|
9bac43 |
@@ -662,7 +662,7 @@ class TracepointProvider(Provider):
|
|
|
9bac43 |
self.setup_traces()
|
|
|
9bac43 |
self.fields = self._fields
|
|
|
9bac43 |
|
|
|
9bac43 |
- def read(self):
|
|
|
9bac43 |
+ def read(self, by_guest=0):
|
|
|
9bac43 |
"""Returns 'event name: current value' for all enabled events."""
|
|
|
9bac43 |
ret = defaultdict(int)
|
|
|
9bac43 |
for group in self.group_leaders:
|
|
|
9bac43 |
@@ -731,7 +731,7 @@ class DebugfsProvider(Provider):
|
|
|
9bac43 |
self.do_read = True
|
|
|
9bac43 |
self.reset()
|
|
|
9bac43 |
|
|
|
9bac43 |
- def read(self, reset=0):
|
|
|
9bac43 |
+ def read(self, reset=0, by_guest=0):
|
|
|
9bac43 |
"""Returns a dict with format:'file name / field -> current value'.
|
|
|
9bac43 |
|
|
|
9bac43 |
Parameter 'reset':
|
|
|
9bac43 |
@@ -762,8 +762,16 @@ class DebugfsProvider(Provider):
|
|
|
9bac43 |
self._baseline[key] = 0
|
|
|
9bac43 |
if self._baseline.get(key, -1) == -1:
|
|
|
9bac43 |
self._baseline[key] = value
|
|
|
9bac43 |
- results[field] = (results.get(field, 0) + value -
|
|
|
9bac43 |
- self._baseline.get(key, 0))
|
|
|
9bac43 |
+ increment = (results.get(field, 0) + value -
|
|
|
9bac43 |
+ self._baseline.get(key, 0))
|
|
|
9bac43 |
+ if by_guest:
|
|
|
9bac43 |
+ pid = key.split('-')[0]
|
|
|
9bac43 |
+ if pid in results:
|
|
|
9bac43 |
+ results[pid] += increment
|
|
|
9bac43 |
+ else:
|
|
|
9bac43 |
+ results[pid] = increment
|
|
|
9bac43 |
+ else:
|
|
|
9bac43 |
+ results[field] = increment
|
|
|
9bac43 |
|
|
|
9bac43 |
return results
|
|
|
9bac43 |
|
|
|
9bac43 |
@@ -849,18 +857,44 @@ class Stats(object):
|
|
|
9bac43 |
for provider in self.providers:
|
|
|
9bac43 |
provider.pid = self._pid_filter
|
|
|
9bac43 |
|
|
|
9bac43 |
- def get(self):
|
|
|
9bac43 |
+ def get(self, by_guest=0):
|
|
|
9bac43 |
"""Returns a dict with field -> (value, delta to last value) of all
|
|
|
9bac43 |
provider data."""
|
|
|
9bac43 |
for provider in self.providers:
|
|
|
9bac43 |
- new = provider.read()
|
|
|
9bac43 |
- for key in provider.fields:
|
|
|
9bac43 |
+ new = provider.read(by_guest=by_guest)
|
|
|
9bac43 |
+ for key in new if by_guest else provider.fields:
|
|
|
9bac43 |
oldval = self.values.get(key, (0, 0))[0]
|
|
|
9bac43 |
newval = new.get(key, 0)
|
|
|
9bac43 |
newdelta = newval - oldval
|
|
|
9bac43 |
self.values[key] = (newval, newdelta)
|
|
|
9bac43 |
return self.values
|
|
|
9bac43 |
|
|
|
9bac43 |
+ def toggle_display_guests(self, to_pid):
|
|
|
9bac43 |
+ """Toggle between collection of stats by individual event and by
|
|
|
9bac43 |
+ guest pid
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+ Events reported by DebugfsProvider change when switching to/from
|
|
|
9bac43 |
+ reading by guest values. Hence we have to remove the excess event
|
|
|
9bac43 |
+ names from self.values.
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+ """
|
|
|
9bac43 |
+ if any(isinstance(ins, TracepointProvider) for ins in self.providers):
|
|
|
9bac43 |
+ return 1
|
|
|
9bac43 |
+ if to_pid:
|
|
|
9bac43 |
+ for provider in self.providers:
|
|
|
9bac43 |
+ if isinstance(provider, DebugfsProvider):
|
|
|
9bac43 |
+ for key in provider.fields:
|
|
|
9bac43 |
+ if key in self.values.keys():
|
|
|
9bac43 |
+ del self.values[key]
|
|
|
9bac43 |
+ else:
|
|
|
9bac43 |
+ oldvals = self.values.copy()
|
|
|
9bac43 |
+ for key in oldvals:
|
|
|
9bac43 |
+ if key.isdigit():
|
|
|
9bac43 |
+ del self.values[key]
|
|
|
9bac43 |
+ # Update oldval (see get())
|
|
|
9bac43 |
+ self.get(to_pid)
|
|
|
9bac43 |
+ return 0
|
|
|
9bac43 |
+
|
|
|
9bac43 |
DELAY_DEFAULT = 3.0
|
|
|
9bac43 |
MAX_GUEST_NAME_LEN = 48
|
|
|
9bac43 |
MAX_REGEX_LEN = 44
|
|
|
9bac43 |
@@ -876,6 +910,7 @@ class Tui(object):
|
|
|
9bac43 |
self._delay_initial = 0.25
|
|
|
9bac43 |
self._delay_regular = DELAY_DEFAULT
|
|
|
9bac43 |
self._sorting = SORT_DEFAULT
|
|
|
9bac43 |
+ self._display_guests = 0
|
|
|
9bac43 |
|
|
|
9bac43 |
def __enter__(self):
|
|
|
9bac43 |
"""Initialises curses for later use. Based on curses.wrapper
|
|
|
9bac43 |
@@ -1024,8 +1059,12 @@ class Tui(object):
|
|
|
9bac43 |
if len(regex) > MAX_REGEX_LEN:
|
|
|
9bac43 |
regex = regex[:MAX_REGEX_LEN] + '...'
|
|
|
9bac43 |
self.screen.addstr(1, 17, 'regex filter: {0}'.format(regex))
|
|
|
9bac43 |
+ if self._display_guests:
|
|
|
9bac43 |
+ col_name = 'Guest Name'
|
|
|
9bac43 |
+ else:
|
|
|
9bac43 |
+ col_name = 'Event'
|
|
|
9bac43 |
self.screen.addstr(2, 1, '%-40s %10s%7s %8s' %
|
|
|
9bac43 |
- ('Event', 'Total', '%Total', 'CurAvg/s'),
|
|
|
9bac43 |
+ (col_name, 'Total', '%Total', 'CurAvg/s'),
|
|
|
9bac43 |
curses.A_STANDOUT)
|
|
|
9bac43 |
self.screen.addstr(4, 1, 'Collecting data...')
|
|
|
9bac43 |
self.screen.refresh()
|
|
|
9bac43 |
@@ -1034,7 +1073,7 @@ class Tui(object):
|
|
|
9bac43 |
row = 3
|
|
|
9bac43 |
self.screen.move(row, 0)
|
|
|
9bac43 |
self.screen.clrtobot()
|
|
|
9bac43 |
- stats = self.stats.get()
|
|
|
9bac43 |
+ stats = self.stats.get(self._display_guests)
|
|
|
9bac43 |
|
|
|
9bac43 |
def sortCurAvg(x):
|
|
|
9bac43 |
# sort by current events if available
|
|
|
9bac43 |
@@ -1062,6 +1101,8 @@ class Tui(object):
|
|
|
9bac43 |
break
|
|
|
9bac43 |
if values[0] is not None:
|
|
|
9bac43 |
cur = int(round(values[1] / sleeptime)) if values[1] else ''
|
|
|
9bac43 |
+ if self._display_guests:
|
|
|
9bac43 |
+ key = self.get_gname_from_pid(key)
|
|
|
9bac43 |
self.screen.addstr(row, 1, '%-40s %10d%7.1f %8s' %
|
|
|
9bac43 |
(key, values[0], values[0] * 100 / total,
|
|
|
9bac43 |
cur))
|
|
|
9bac43 |
@@ -1070,9 +1111,26 @@ class Tui(object):
|
|
|
9bac43 |
self.screen.addstr(4, 1, 'No matching events reported yet')
|
|
|
9bac43 |
self.screen.refresh()
|
|
|
9bac43 |
|
|
|
9bac43 |
+ def show_msg(self, text):
|
|
|
9bac43 |
+ """Display message centered text and exit on key press"""
|
|
|
9bac43 |
+ hint = 'Press any key to continue'
|
|
|
9bac43 |
+ curses.cbreak()
|
|
|
9bac43 |
+ self.screen.erase()
|
|
|
9bac43 |
+ (x, term_width) = self.screen.getmaxyx()
|
|
|
9bac43 |
+ row = 2
|
|
|
9bac43 |
+ for line in text:
|
|
|
9bac43 |
+ start = (term_width - len(line)) / 2
|
|
|
9bac43 |
+ self.screen.addstr(row, start, line)
|
|
|
9bac43 |
+ row += 1
|
|
|
9bac43 |
+ self.screen.addstr(row + 1, (term_width - len(hint)) / 2, hint,
|
|
|
9bac43 |
+ curses.A_STANDOUT)
|
|
|
9bac43 |
+ self.screen.getkey()
|
|
|
9bac43 |
+
|
|
|
9bac43 |
def show_help_interactive(self):
|
|
|
9bac43 |
"""Display help with list of interactive commands"""
|
|
|
9bac43 |
- msg = (' c clear filter',
|
|
|
9bac43 |
+ msg = (' b toggle events by guests (debugfs only, honors'
|
|
|
9bac43 |
+ ' filters)',
|
|
|
9bac43 |
+ ' c clear filter',
|
|
|
9bac43 |
' f filter by regular expression',
|
|
|
9bac43 |
' g filter by guest name',
|
|
|
9bac43 |
' h display interactive commands reference',
|
|
|
9bac43 |
@@ -1253,6 +1311,14 @@ class Tui(object):
|
|
|
9bac43 |
sleeptime = self._delay_regular
|
|
|
9bac43 |
try:
|
|
|
9bac43 |
char = self.screen.getkey()
|
|
|
9bac43 |
+ if char == 'b':
|
|
|
9bac43 |
+ self._display_guests = not self._display_guests
|
|
|
9bac43 |
+ if self.stats.toggle_display_guests(self._display_guests):
|
|
|
9bac43 |
+ self.show_msg(['Command not available with tracepoints'
|
|
|
9bac43 |
+ ' enabled', 'Restart with debugfs only '
|
|
|
9bac43 |
+ '(see option \'-d\') and try again!'])
|
|
|
9bac43 |
+ self._display_guests = not self._display_guests
|
|
|
9bac43 |
+ self.refresh_header()
|
|
|
9bac43 |
if char == 'c':
|
|
|
9bac43 |
self.stats.fields_filter = DEFAULT_REGEX
|
|
|
9bac43 |
self.refresh_header(0)
|
|
|
9bac43 |
@@ -1356,6 +1422,7 @@ Requirements:
|
|
|
9bac43 |
the large number of files that are possibly opened.
|
|
|
9bac43 |
|
|
|
9bac43 |
Interactive Commands:
|
|
|
9bac43 |
+ b toggle events by guests (debugfs only, honors filters)
|
|
|
9bac43 |
c clear filter
|
|
|
9bac43 |
f filter by regular expression
|
|
|
9bac43 |
g filter by guest name
|
|
|
9bac43 |
diff --git a/scripts/kvm/kvm_stat.texi b/scripts/kvm/kvm_stat.texi
|
|
|
9bac43 |
index b0e282a..5d964f6 100644
|
|
|
9bac43 |
--- a/scripts/kvm/kvm_stat.texi
|
|
|
9bac43 |
+++ b/scripts/kvm/kvm_stat.texi
|
|
|
9bac43 |
@@ -24,6 +24,9 @@ Use batch and logging modes for scripting purposes.
|
|
|
9bac43 |
While running in regular (interactive) mode, use any of the following keys:
|
|
|
9bac43 |
|
|
|
9bac43 |
@table @key
|
|
|
9bac43 |
+@item b
|
|
|
9bac43 |
+@kindex b
|
|
|
9bac43 |
+toggle events by guests (debugfs only, honors filters)
|
|
|
9bac43 |
@item c
|
|
|
9bac43 |
@kindex c
|
|
|
9bac43 |
clear filter
|
|
|
9bac43 |
--
|
|
|
9bac43 |
1.8.3.1
|
|
|
9bac43 |
|