Blob Blame History Raw
From 5bf653923c85a01b85fe801b3a752938424ce659 Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Tue, 17 Oct 2017 19:15:33 +0200
Subject: [PATCH 28/69] tools/kvm_stat: reduce perceived idle time on filter
 updates
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

RH-Author: David Hildenbrand <david@redhat.com>
Message-id: <20171017191605.2378-8-david@redhat.com>
Patchwork-id: 77314
O-Subject: [RHEL-7.5 qemu-kvm-rhev PATCH 07/39] tools/kvm_stat: reduce perceived idle time on filter updates
Bugzilla: 1497137
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
RH-Acked-by: Thomas Huth <thuth@redhat.com>

Upstream-status: linux.git 184b2d23b057b35fba7fd4049962a897ef0e3f9d

commit 184b2d23b057b35fba7fd4049962a897ef0e3f9d
Author: Stefan Raspl <raspl@linux.vnet.ibm.com>
Date:   Fri Mar 10 13:40:06 2017 +0100

    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>

Signed-off-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 scripts/kvm/kvm_stat | 48 ++++++++++++++++++++++++++++++------------------
 1 file changed, 30 insertions(+), 18 deletions(-)

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