* [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 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