diff options
author | Stefan Raspl | 2017-03-10 06:40:06 -0600 |
---|---|---|
committer | Paolo Bonzini | 2017-03-29 05:01:27 -0500 |
commit | 184b2d23b057b35fba7fd4049962a897ef0e3f9d (patch) | |
tree | bac84a46b31f5eb514288408cb5f6882f6399e0a /tools | |
parent | 692c7f6deb553dde2531102cd10ac17ab61438e4 (diff) | |
download | kernel-184b2d23b057b35fba7fd4049962a897ef0e3f9d.tar.gz kernel-184b2d23b057b35fba7fd4049962a897ef0e3f9d.tar.xz kernel-184b2d23b057b35fba7fd4049962a897ef0e3f9d.zip |
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>
Diffstat (limited to 'tools')
-rwxr-xr-x | tools/kvm/kvm_stat/kvm_stat | 48 |
1 files changed, 30 insertions, 18 deletions
diff --git a/tools/kvm/kvm_stat/kvm_stat b/tools/kvm/kvm_stat/kvm_stat index 5c4f24879dc4..3e60d93870c0 100755 --- a/tools/kvm/kvm_stat/kvm_stat +++ b/tools/kvm/kvm_stat/kvm_stat | |||
@@ -801,6 +801,8 @@ class Stats(object): | |||
801 | 801 | ||
802 | LABEL_WIDTH = 40 | 802 | LABEL_WIDTH = 40 |
803 | NUMBER_WIDTH = 10 | 803 | NUMBER_WIDTH = 10 |
804 | DELAY_INITIAL = 0.25 | ||
805 | DELAY_REGULAR = 3.0 | ||
804 | 806 | ||
805 | 807 | ||
806 | class Tui(object): | 808 | class Tui(object): |
@@ -856,13 +858,14 @@ class Tui(object): | |||
856 | """Propagates pid selection to stats object.""" | 858 | """Propagates pid selection to stats object.""" |
857 | self.stats.pid_filter = pid | 859 | self.stats.pid_filter = pid |
858 | 860 | ||
859 | def refresh(self, sleeptime): | 861 | def refresh_header(self, pid=None): |
860 | """Refreshes on-screen data.""" | 862 | """Refreshes the header.""" |
863 | if pid is None: | ||
864 | pid = self.stats.pid_filter | ||
861 | self.screen.erase() | 865 | self.screen.erase() |
862 | if self.stats.pid_filter > 0: | 866 | if pid > 0: |
863 | self.screen.addstr(0, 0, 'kvm statistics - pid {0}' | 867 | self.screen.addstr(0, 0, 'kvm statistics - pid {0}' |
864 | .format(self.stats.pid_filter), | 868 | .format(pid), curses.A_BOLD) |
865 | curses.A_BOLD) | ||
866 | else: | 869 | else: |
867 | self.screen.addstr(0, 0, 'kvm statistics - summary', curses.A_BOLD) | 870 | self.screen.addstr(0, 0, 'kvm statistics - summary', curses.A_BOLD) |
868 | self.screen.addstr(2, 1, 'Event') | 871 | self.screen.addstr(2, 1, 'Event') |
@@ -870,7 +873,13 @@ class Tui(object): | |||
870 | len('Total'), 'Total') | 873 | len('Total'), 'Total') |
871 | self.screen.addstr(2, 1 + LABEL_WIDTH + NUMBER_WIDTH + 8 - | 874 | self.screen.addstr(2, 1 + LABEL_WIDTH + NUMBER_WIDTH + 8 - |
872 | len('Current'), 'Current') | 875 | len('Current'), 'Current') |
876 | self.screen.addstr(4, 1, 'Collecting data...') | ||
877 | self.screen.refresh() | ||
878 | |||
879 | def refresh_body(self, sleeptime): | ||
873 | row = 3 | 880 | row = 3 |
881 | self.screen.move(row, 0) | ||
882 | self.screen.clrtobot() | ||
874 | stats = self.stats.get() | 883 | stats = self.stats.get() |
875 | 884 | ||
876 | def sortkey(x): | 885 | def sortkey(x): |
@@ -914,10 +923,12 @@ class Tui(object): | |||
914 | regex = self.screen.getstr() | 923 | regex = self.screen.getstr() |
915 | curses.noecho() | 924 | curses.noecho() |
916 | if len(regex) == 0: | 925 | if len(regex) == 0: |
926 | self.refresh_header() | ||
917 | return | 927 | return |
918 | try: | 928 | try: |
919 | re.compile(regex) | 929 | re.compile(regex) |
920 | self.stats.fields_filter = regex | 930 | self.stats.fields_filter = regex |
931 | self.refresh_header() | ||
921 | return | 932 | return |
922 | except re.error: | 933 | except re.error: |
923 | continue | 934 | continue |
@@ -944,37 +955,38 @@ class Tui(object): | |||
944 | 955 | ||
945 | try: | 956 | try: |
946 | pid = int(pid) | 957 | pid = int(pid) |
947 | 958 | if pid != 0 and not os.path.isdir(os.path.join('/proc/', | |
948 | if pid == 0: | 959 | str(pid))): |
949 | self.update_pid(pid) | 960 | continue |
950 | break | 961 | self.refresh_header(pid) |
951 | else: | 962 | self.update_pid(pid) |
952 | if not os.path.isdir(os.path.join('/proc/', str(pid))): | 963 | break |
953 | continue | ||
954 | else: | ||
955 | self.update_pid(pid) | ||
956 | break | ||
957 | 964 | ||
958 | except ValueError: | 965 | except ValueError: |
959 | continue | 966 | continue |
960 | 967 | ||
961 | def show_stats(self): | 968 | def show_stats(self): |
962 | """Refreshes the screen and processes user input.""" | 969 | """Refreshes the screen and processes user input.""" |
963 | sleeptime = 0.25 | 970 | sleeptime = DELAY_INITIAL |
971 | self.refresh_header() | ||
964 | while True: | 972 | while True: |
965 | self.refresh(sleeptime) | 973 | self.refresh_body(sleeptime) |
966 | curses.halfdelay(int(sleeptime * 10)) | 974 | curses.halfdelay(int(sleeptime * 10)) |
967 | sleeptime = 3.0 | 975 | sleeptime = DELAY_REGULAR |
968 | try: | 976 | try: |
969 | char = self.screen.getkey() | 977 | char = self.screen.getkey() |
970 | if char == 'x': | 978 | if char == 'x': |
979 | self.refresh_header() | ||
971 | self.update_drilldown() | 980 | self.update_drilldown() |
981 | sleeptime = DELAY_INITIAL | ||
972 | if char == 'q': | 982 | if char == 'q': |
973 | break | 983 | break |
974 | if char == 'f': | 984 | if char == 'f': |
975 | self.show_filter_selection() | 985 | self.show_filter_selection() |
986 | sleeptime = DELAY_INITIAL | ||
976 | if char == 'p': | 987 | if char == 'p': |
977 | self.show_vm_selection() | 988 | self.show_vm_selection() |
989 | sleeptime = DELAY_INITIAL | ||
978 | except KeyboardInterrupt: | 990 | except KeyboardInterrupt: |
979 | break | 991 | break |
980 | except curses.error: | 992 | except curses.error: |