tools/kvm_stat: reduce perceived idle time on filter updates

Whenever a user adds a filter, we
* redraw the header immediately for a snappy response
* print a message indicating to the user that we're busy while the
  noticeable delay induced by updating all of the stats objects takes place
* update the statistics ASAP (i.e. after 0.25s instead of 3s) to be
  consistent with behavior on startup
To do so, we split the Tui's refresh() method to allow for drawing header
and stats separately, and trigger a header refresh whenever we are about
to do something that takes a while - like updating filters.

Signed-off-by: Stefan Raspl <raspl@linux.vnet.ibm.com>
Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
This commit is contained in:
Stefan Raspl 2017-03-10 13:40:06 +01:00 committed by Paolo Bonzini
parent 692c7f6deb
commit 184b2d23b0
1 changed files with 30 additions and 18 deletions

View File

@ -801,6 +801,8 @@ class Stats(object):
LABEL_WIDTH = 40 LABEL_WIDTH = 40
NUMBER_WIDTH = 10 NUMBER_WIDTH = 10
DELAY_INITIAL = 0.25
DELAY_REGULAR = 3.0
class Tui(object): class Tui(object):
@ -856,13 +858,14 @@ class Tui(object):
"""Propagates pid selection to stats object.""" """Propagates pid selection to stats object."""
self.stats.pid_filter = pid self.stats.pid_filter = pid
def refresh(self, sleeptime): def refresh_header(self, pid=None):
"""Refreshes on-screen data.""" """Refreshes the header."""
if pid is None:
pid = self.stats.pid_filter
self.screen.erase() self.screen.erase()
if self.stats.pid_filter > 0: if pid > 0:
self.screen.addstr(0, 0, 'kvm statistics - pid {0}' self.screen.addstr(0, 0, 'kvm statistics - pid {0}'
.format(self.stats.pid_filter), .format(pid), curses.A_BOLD)
curses.A_BOLD)
else: else:
self.screen.addstr(0, 0, 'kvm statistics - summary', curses.A_BOLD) self.screen.addstr(0, 0, 'kvm statistics - summary', curses.A_BOLD)
self.screen.addstr(2, 1, 'Event') self.screen.addstr(2, 1, 'Event')
@ -870,7 +873,13 @@ class Tui(object):
len('Total'), 'Total') len('Total'), 'Total')
self.screen.addstr(2, 1 + LABEL_WIDTH + NUMBER_WIDTH + 8 - self.screen.addstr(2, 1 + LABEL_WIDTH + NUMBER_WIDTH + 8 -
len('Current'), 'Current') len('Current'), 'Current')
self.screen.addstr(4, 1, 'Collecting data...')
self.screen.refresh()
def refresh_body(self, sleeptime):
row = 3 row = 3
self.screen.move(row, 0)
self.screen.clrtobot()
stats = self.stats.get() stats = self.stats.get()
def sortkey(x): def sortkey(x):
@ -914,10 +923,12 @@ class Tui(object):
regex = self.screen.getstr() regex = self.screen.getstr()
curses.noecho() curses.noecho()
if len(regex) == 0: if len(regex) == 0:
self.refresh_header()
return return
try: try:
re.compile(regex) re.compile(regex)
self.stats.fields_filter = regex self.stats.fields_filter = regex
self.refresh_header()
return return
except re.error: except re.error:
continue continue
@ -944,37 +955,38 @@ class Tui(object):
try: try:
pid = int(pid) pid = int(pid)
if pid != 0 and not os.path.isdir(os.path.join('/proc/',
if pid == 0: str(pid))):
self.update_pid(pid) continue
break self.refresh_header(pid)
else: self.update_pid(pid)
if not os.path.isdir(os.path.join('/proc/', str(pid))): break
continue
else:
self.update_pid(pid)
break
except ValueError: except ValueError:
continue continue
def show_stats(self): def show_stats(self):
"""Refreshes the screen and processes user input.""" """Refreshes the screen and processes user input."""
sleeptime = 0.25 sleeptime = DELAY_INITIAL
self.refresh_header()
while True: while True:
self.refresh(sleeptime) self.refresh_body(sleeptime)
curses.halfdelay(int(sleeptime * 10)) curses.halfdelay(int(sleeptime * 10))
sleeptime = 3.0 sleeptime = DELAY_REGULAR
try: try:
char = self.screen.getkey() char = self.screen.getkey()
if char == 'x': if char == 'x':
self.refresh_header()
self.update_drilldown() self.update_drilldown()
sleeptime = DELAY_INITIAL
if char == 'q': if char == 'q':
break break
if char == 'f': if char == 'f':
self.show_filter_selection() self.show_filter_selection()
sleeptime = DELAY_INITIAL
if char == 'p': if char == 'p':
self.show_vm_selection() self.show_vm_selection()
sleeptime = DELAY_INITIAL
except KeyboardInterrupt: except KeyboardInterrupt:
break break
except curses.error: except curses.error: