public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] Enable drilldown for kvm_exit reasons
@ 2011-02-17 12:42 Avi Kivity
  2011-02-17 12:42 ` [PATCH 1/4] kvm_stat: move groups and events into well defined objects Avi Kivity
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Avi Kivity @ 2011-02-17 12:42 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

kvm_stat currently tracks both tracepoints, and also kvm_exit by exit reason.
This is somewhat cluttered and also very expensive with the current
kernel filter implementation.

Make drilldown optional by adding a key to trigger it.

Avi Kivity (4):
  kvm_stat: move groups and events into well defined objects
  kvm_stat: add wrappers for perf_event enable and disable ioctls
  kvm_stat: allow enabling/disabling events dynamicalls
  kvm_stat: add 'x' key for enabling/disabling "drilldown"

 kvm/kvm_stat |  149 ++++++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 103 insertions(+), 46 deletions(-)


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/4] kvm_stat: move groups and events into well defined objects
  2011-02-17 12:42 [PATCH 0/4] Enable drilldown for kvm_exit reasons Avi Kivity
@ 2011-02-17 12:42 ` Avi Kivity
  2011-02-17 12:42 ` [PATCH 2/4] kvm_stat: add wrappers for perf_event enable and disable ioctls Avi Kivity
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Avi Kivity @ 2011-02-17 12:42 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 kvm/kvm_stat |  107 +++++++++++++++++++++++++++++++++++----------------------
 1 files changed, 66 insertions(+), 41 deletions(-)

diff --git a/kvm/kvm_stat b/kvm/kvm_stat
index f8a1399..371e547 100755
--- a/kvm/kvm_stat
+++ b/kvm/kvm_stat
@@ -201,12 +201,57 @@ PERF_FORMAT_GROUP			= 1 << 3
 
 import re
 
+sys_tracing = '/sys/kernel/debug/tracing'
+
+class Group(object):
+    def __init__(self, cpu):
+        self.events = []
+        self.group_leader = None
+        self.cpu = cpu
+    def add_event(self, name, event_set, tracepoint, filter = None):
+        self.events.append(Event(group = self,
+                                 name = name, event_set = event_set,
+                                 tracepoint = tracepoint, filter = filter))
+        if len(self.events) == 1:
+            self.file = os.fdopen(self.events[0].fd)
+    def read(self):
+        bytes = 8 * (1 + len(self.events))
+        fmt = 'xxxxxxxx' + 'q' * len(self.events)
+        return dict(zip([event.name for event in self.events],
+                        struct.unpack(fmt, self.file.read(bytes))))
+
+class Event(object):
+    def __init__(self, group, name, event_set, tracepoint, filter = None):
+        self.name = name
+        attr = perf_event_attr()
+        attr.type = PERF_TYPE_TRACEPOINT
+        attr.size = ctypes.sizeof(attr)
+        id_path = os.path.join(sys_tracing, 'events', event_set,
+                               tracepoint, 'id')
+        id = int(file(id_path).read())
+        attr.config = id
+        attr.sample_type = (PERF_SAMPLE_RAW
+                            | PERF_SAMPLE_TIME
+                            | PERF_SAMPLE_CPU)
+        attr.sample_period = 1
+        attr.read_format = PERF_FORMAT_GROUP
+        group_leader = -1
+        if group.events:
+            group_leader = group.events[0].fd
+        fd = _perf_event_open(attr, -1, group.cpu, group_leader, 0)
+        if fd == -1:
+            raise Exception('perf_event_open failed')
+        if filter:
+            import fcntl
+            fcntl.ioctl(fd, 0x40082406, filter)
+        self.fd = fd
+
 class TracepointProvider(object):
     def __init__(self):
-        self.base = '/sys/kernel/debug/tracing/events/kvm/'
+        path = os.path.join(sys_tracing, 'events', 'kvm')
         fields = [f
-                  for f in os.listdir(self.base)
-                  if os.path.isdir(self.base + '/' + f)]
+                  for f in os.listdir(path)
+                  if os.path.isdir(os.path.join(path, f))]
         extra = []
         for f in fields:
             if f in filters:
@@ -226,48 +271,28 @@ class TracepointProvider(object):
         import resource
         nfiles = len(self.cpus) * 1000
         resource.setrlimit(resource.RLIMIT_NOFILE, (nfiles, nfiles))
-        fds = []
+        events = []
         self.group_leaders = []
         for cpu in self.cpus:
-            group_leader = -1
-            for f in _fields:
-                fbase, sub = f, None
-                m = re.match(r'(.*)\((.*)\)', f)
+            group = Group(cpu)
+            for name in _fields:
+                tracepoint = name
+                filter = None
+                m = re.match(r'(.*)\((.*)\)', name)
                 if m:
-                    fbase, sub = m.groups()
-                attr = perf_event_attr()
-                attr.type = PERF_TYPE_TRACEPOINT
-                attr.size = ctypes.sizeof(attr)
-                id = int(file(self.base + fbase + '/id').read())
-                attr.config = id
-                attr.sample_type = (PERF_SAMPLE_RAW
-                                    | PERF_SAMPLE_TIME
-                                    | PERF_SAMPLE_CPU)
-                attr.sample_period = 1
-                attr.read_format = PERF_FORMAT_GROUP
-                fd = _perf_event_open(attr, -1, cpu, group_leader, 0)
-                if fd == -1:
-                    raise Exception('perf_event_open failed')
-                if sub:
-                    import fcntl
-                    filter = '%s==%d\0' % (filters[fbase][0],
-                                         filters[fbase][1][sub])
-                    fcntl.ioctl(fd, 0x40082406, filter)
-                if group_leader == -1:
-                    group_leader = fd
-                    fds.append(fd)
-            self.group_leaders.append(group_leader)
-        self.fds = fds
-        self.files = [os.fdopen(group_leader)
-                      for group_leader in self.group_leaders]
+                    tracepoint, sub = m.groups()
+                    filter = '%s==%d\0' % (filters[tracepoint][0],
+                                           filters[tracepoint][1][sub])
+                event = group.add_event(name, event_set = 'kvm',
+                                        tracepoint = tracepoint,
+                                        filter = filter)
+            self.group_leaders.append(group)
     def read(self):
-        ret = dict([(f, 0) for f in self._fields])
-        bytes = 8 * (1 + len(self._fields))
-        fmt = 'xxxxxxxx' + 'q' * len(self._fields)
-        for file in self.files:
-            a = struct.unpack(fmt, file.read(bytes))
-            for field, val in zip(self._fields, a):
-                ret[field] += val
+        from collections import defaultdict
+        ret = defaultdict(int)
+        for group in self.group_leaders:
+            for name, val in group.read().iteritems():
+                ret[name] += val
         return ret
 
 class Stats:
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/4] kvm_stat: add wrappers for perf_event enable and disable ioctls
  2011-02-17 12:42 [PATCH 0/4] Enable drilldown for kvm_exit reasons Avi Kivity
  2011-02-17 12:42 ` [PATCH 1/4] kvm_stat: move groups and events into well defined objects Avi Kivity
@ 2011-02-17 12:42 ` Avi Kivity
  2011-02-17 12:42 ` [PATCH 3/4] kvm_stat: allow enabling/disabling events dynamicalls Avi Kivity
  2011-02-17 12:42 ` [PATCH 4/4] kvm_stat: add 'x' key for enabling/disabling "drilldown" Avi Kivity
  3 siblings, 0 replies; 5+ messages in thread
From: Avi Kivity @ 2011-02-17 12:42 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 kvm/kvm_stat |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/kvm/kvm_stat b/kvm/kvm_stat
index 371e547..2e1fe73 100755
--- a/kvm/kvm_stat
+++ b/kvm/kvm_stat
@@ -245,6 +245,12 @@ class Event(object):
             import fcntl
             fcntl.ioctl(fd, 0x40082406, filter)
         self.fd = fd
+    def enable(self):
+        import fcntl
+        fcntl.ioctl(self.fd, 0x00002400, 0)
+    def disable(self):
+        import fcntl
+        fcntl.ioctl(self.fd, 0x00002401, 0)
 
 class TracepointProvider(object):
     def __init__(self):
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/4] kvm_stat: allow enabling/disabling events dynamicalls
  2011-02-17 12:42 [PATCH 0/4] Enable drilldown for kvm_exit reasons Avi Kivity
  2011-02-17 12:42 ` [PATCH 1/4] kvm_stat: move groups and events into well defined objects Avi Kivity
  2011-02-17 12:42 ` [PATCH 2/4] kvm_stat: add wrappers for perf_event enable and disable ioctls Avi Kivity
@ 2011-02-17 12:42 ` Avi Kivity
  2011-02-17 12:42 ` [PATCH 4/4] kvm_stat: add 'x' key for enabling/disabling "drilldown" Avi Kivity
  3 siblings, 0 replies; 5+ messages in thread
From: Avi Kivity @ 2011-02-17 12:42 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 kvm/kvm_stat |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/kvm/kvm_stat b/kvm/kvm_stat
index 2e1fe73..e3e9def 100755
--- a/kvm/kvm_stat
+++ b/kvm/kvm_stat
@@ -265,10 +265,11 @@ class TracepointProvider(object):
                 for name, number in values.iteritems():
                     extra.append(f + '(' + name + ')')
         fields += extra
+        self._setup(fields)
         self.select(fields)
     def fields(self):
         return self._fields
-    def select(self, _fields):
+    def _setup(self, _fields):
         self._fields = _fields
         cpure = r'cpu([0-9]+)'
         self.cpus = [int(re.match(cpure, x).group(1))
@@ -293,6 +294,13 @@ class TracepointProvider(object):
                                         tracepoint = tracepoint,
                                         filter = filter)
             self.group_leaders.append(group)
+    def select(self, fields):
+        for group in self.group_leaders:
+            for event in group.events:
+                if event.name in fields:
+                    event.enable()
+                else:
+                    event.disable()
     def read(self):
         from collections import defaultdict
         ret = defaultdict(int)
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 4/4] kvm_stat: add 'x' key for enabling/disabling "drilldown"
  2011-02-17 12:42 [PATCH 0/4] Enable drilldown for kvm_exit reasons Avi Kivity
                   ` (2 preceding siblings ...)
  2011-02-17 12:42 ` [PATCH 3/4] kvm_stat: allow enabling/disabling events dynamicalls Avi Kivity
@ 2011-02-17 12:42 ` Avi Kivity
  3 siblings, 0 replies; 5+ messages in thread
From: Avi Kivity @ 2011-02-17 12:42 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

Pressing 'x' enables drilldown into kvm_exit reasons.  Pressing it
again reverts to normal behaviour.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 kvm/kvm_stat |   26 ++++++++++++++++++++++----
 1 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/kvm/kvm_stat b/kvm/kvm_stat
index e3e9def..db2d135 100755
--- a/kvm/kvm_stat
+++ b/kvm/kvm_stat
@@ -311,20 +311,26 @@ class TracepointProvider(object):
 
 class Stats:
     def __init__(self, provider, fields = None):
+        self.provider = provider
+        self.fields_filter = fields
+        self._update()
+    def _update(self):
         def wanted(key):
             import re
-            if not fields:
+            if not self.fields_filter:
                 return True
-            return re.match(fields, key) != None
-        self.provider = provider
+            return re.match(self.fields_filter, key) is not None
         self.values = dict([(key, None)
                             for key in provider.fields()
                             if wanted(key)])
         self.provider.select(self.values.keys())
+    def set_fields_filter(self, fields_filter):
+        self.fields_filter = fields_filter
+        self._update()
     def get(self):
         new = self.provider.read()
         for key in self.provider.fields():
-            oldval = self.values[key]
+            oldval = self.values.get(key, (0, 0))
             newval = new[key]
             newdelta = None
             if oldval is not None:
@@ -346,6 +352,15 @@ number_width = 10
 def tui(screen, stats):
     curses.use_default_colors()
     curses.noecho()
+    drilldown = False
+    fields_filter = stats.fields_filter
+    def update_drilldown():
+        if not fields_filter:
+            if drilldown:
+                stats.set_fields_filter(None)
+            else:
+                stats.set_fields_filter(r'^[^\(]*$')
+    update_drilldown()
     def refresh(sleeptime):
         screen.erase()
         screen.addstr(0, 0, 'kvm statistics')
@@ -379,6 +394,9 @@ def tui(screen, stats):
         sleeptime = 3
         try:
             c = screen.getkey()
+            if c == 'x':
+                drilldown = not drilldown
+                update_drilldown()
             if c == 'q':
                 break
         except KeyboardInterrupt:
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2011-02-17 12:43 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-02-17 12:42 [PATCH 0/4] Enable drilldown for kvm_exit reasons Avi Kivity
2011-02-17 12:42 ` [PATCH 1/4] kvm_stat: move groups and events into well defined objects Avi Kivity
2011-02-17 12:42 ` [PATCH 2/4] kvm_stat: add wrappers for perf_event enable and disable ioctls Avi Kivity
2011-02-17 12:42 ` [PATCH 3/4] kvm_stat: allow enabling/disabling events dynamicalls Avi Kivity
2011-02-17 12:42 ` [PATCH 4/4] kvm_stat: add 'x' key for enabling/disabling "drilldown" Avi Kivity

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox