summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2011-01-29 17:50:22 -0200
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-01-29 17:50:22 -0200
commit00a2aa467ae3a5a750df99f88f765e9b5829e493 (patch)
tree871b5b34c902019ff6279cbd434bd80dd2ffb6ce
parentf130d846bc52caddbbc35ead7b18772a10ee0141 (diff)
downloadtuna-00a2aa467ae3a5a750df99f88f765e9b5829e493.tar.gz
gui: Use perf if available
So that we can have access to all sorts of hardware and software counters and as well stop polling /proc to notice new threads and threads dying. To check that it is using, see the signature one mmap per cpu mmaps + the perf.so binding being dlopen'ed by the python interpreter when finding 'import perf', etc. # cat /proc/`pidof tuna`/maps ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] [root@emilia tuna]# cat /proc/1883/maps | grep perf 7fa583072000-7fa5830f3000 rw-s 00000000 00:09 4166 anon_inode:[perf_event] 7fa5830f3000-7fa583174000 rw-s 00000000 00:09 4166 anon_inode:[perf_event] 7fa583174000-7fa5831f5000 rw-s 00000000 00:09 4166 anon_inode:[perf_event] 7fa5831f5000-7fa583276000 rw-s 00000000 00:09 4166 anon_inode:[perf_event] 7fa583276000-7fa5832f7000 rw-s 00000000 00:09 4166 anon_inode:[perf_event] 7fa5832f7000-7fa583378000 rw-s 00000000 00:09 4166 anon_inode:[perf_event] 7fa583378000-7fa5833f9000 rw-s 00000000 00:09 4166 anon_inode:[perf_event] 7fa5833f9000-7fa58347a000 rw-s 00000000 00:09 4166 anon_inode:[perf_event] 7fa58347a000-7fa583483000 r-xp 00000000 fd:00 2229604 /home/acme/git/build/perf/lib.linux-x86_64-2.6/perf.so 7fa583483000-7fa583682000 ---p 00009000 fd:00 2229604 /home/acme/git/build/perf/lib.linux-x86_64-2.6/perf.so 7fa583682000-7fa583685000 rw-p 00008000 fd:00 2229604 /home/acme/git/build/perf/lib.linux-x86_64-2.6/perf.so [root@emilia tuna]# Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rwxr-xr-xtuna/gui/procview.py72
-rwxr-xr-xtuna/tuna_gui.py7
2 files changed, 75 insertions, 4 deletions
diff --git a/tuna/gui/procview.py b/tuna/gui/procview.py
index 2f3f3cf..d011f13 100755
--- a/tuna/gui/procview.py
+++ b/tuna/gui/procview.py
@@ -2,7 +2,7 @@ import pygtk
pygtk.require("2.0")
from tuna import tuna, gui
-import gobject, gtk, procfs, re, schedutils
+import gobject, gtk, procfs, re, schedutils, perf
def N_(s):
"""gettext_noop"""
@@ -212,6 +212,12 @@ class procview:
self.treeview = treeview
self.nr_cpus = procfs.cpuinfo().nr_cpus
self.gladefile = gladefile
+
+ self.evlist = None
+ try:
+ self.perf_init()
+ except: # No perf, poll /proc baby, poll
+ pass
if not ps[1]["status"].has_key("voluntary_ctxt_switches"):
self.nr_columns = 5
@@ -222,6 +228,19 @@ class procview:
gui.list_store_column(_("Priority")),
gui.list_store_column(_("Affinity"), gobject.TYPE_STRING),
gui.list_store_column(_("Command Line"), gobject.TYPE_STRING))
+ elif self.evlist: # habemus perf, so lets use the metric we're collecting
+ self.nr_columns = 8
+ ( self.COL_PID, self.COL_POL, self.COL_PRI,
+ self.COL_AFF, self.COL_VOLCTXT, self.NONVOLCTXT,
+ self.COL_PERF, self.COL_CMDLINE ) = range(self.nr_columns)
+ self.columns = (gui.list_store_column(_("PID")),
+ gui.list_store_column(_("Policy"), gobject.TYPE_STRING),
+ gui.list_store_column(_("Priority")),
+ gui.list_store_column(_("Affinity"), gobject.TYPE_STRING),
+ gui.list_store_column(_("VolCtxtSwitch"), gobject.TYPE_UINT),
+ gui.list_store_column(_("NonVolCtxtSwitch"), gobject.TYPE_UINT),
+ gui.list_store_column(_("Cycles"), gobject.TYPE_UINT),
+ gui.list_store_column(_("Command Line"), gobject.TYPE_STRING))
self.tree_store = gtk.TreeStore(*gui.generate_list_store_columns_with_attr(self.columns))
self.treeview.set_model(self.tree_store)
@@ -260,6 +279,53 @@ class procview:
self.cpus_filtered = cpus_filtered
self.refreshing = True
+ def perf_process_events(self, source, condition):
+ had_events = True
+ while had_events:
+ had_events = False
+ for cpu in self.cpu_map:
+ event = self.evlist.read_on_cpu(cpu)
+ if event:
+ had_events = True
+ if event.type == perf.RECORD_FORK:
+ if event.pid == event.tid:
+ try:
+ self.ps.processes[event.pid] = procfs.process(event.pid)
+ except: # short lived thread
+ pass
+ else:
+ self.ps.processes[event.pid].threads.processes[event.tid] = procfs.process(event.tid)
+ elif event.type == perf.RECORD_EXIT:
+ del self.ps[int(event.tid)]
+ elif event.type == perf.RECORD_SAMPLE:
+ tid = event.sample_tid
+ if self.perf_counter.has_key(tid):
+ self.perf_counter[tid] += event.sample_period
+ else:
+ self.perf_counter[tid] = event.sample_period
+
+ self.show()
+ return True
+
+ def perf_init(self):
+ self.cpu_map = perf.cpu_map()
+ self.thread_map = perf.thread_map()
+ self.evsel_cycles = perf.evsel(task = 1, comm = 1,
+ wakeup_events = 1,
+ sample_period = 1,
+ sample_id_all = 1,
+ sample_type = perf.SAMPLE_PERIOD |
+ perf.SAMPLE_CPU |
+ perf.SAMPLE_TID)
+ self.evsel_cycles.open(cpus = self.cpu_map, threads = self.thread_map);
+ self.evlist = perf.evlist()
+ self.evlist.add(self.evsel_cycles)
+ self.evlist.mmap(cpus = self.cpu_map, threads = self.thread_map)
+ self.pollfd = self.evlist.get_pollfd()
+ for f in self.pollfd:
+ gobject.io_add_watch(f, gtk.gdk.INPUT_READ, self.perf_process_events)
+ self.perf_counter = {}
+
def on_query_tooltip(self, treeview, x, y, keyboard_mode, tooltip):
x, y = treeview.convert_widget_to_bin_window_coords(x, y)
ret = treeview.get_path_at_pos(x, y)
@@ -307,6 +373,10 @@ class procview:
try:
new_value[self.COL_VOLCTXT] = int(thread_info["status"]["voluntary_ctxt_switches"])
new_value[self.COL_NONVOLCTXT] = int(thread_info["status"]["nonvoluntary_ctxt_switches"])
+ try:
+ new_value[self.COL_PERF] = self.perf_counter[tid]
+ except:
+ new_value[self.COL_PERF] = 0
except:
pass
diff --git a/tuna/tuna_gui.py b/tuna/tuna_gui.py
index b267aee..4cb6ea8 100755
--- a/tuna/tuna_gui.py
+++ b/tuna/tuna_gui.py
@@ -88,10 +88,11 @@ class main_gui:
self.procview.show()
def refresh(self):
- self.ps.reload()
- self.ps.reload_threads()
+ if not self.procview.evlist: # Poll, as we don't have perf
+ self.ps.reload()
+ self.ps.reload_threads()
+ self.procview.show()
self.irqview.refresh()
- self.procview.show()
return True
def check_root(self):