diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-01-29 17:50:22 -0200 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-01-29 17:50:22 -0200 |
commit | 00a2aa467ae3a5a750df99f88f765e9b5829e493 (patch) | |
tree | 871b5b34c902019ff6279cbd434bd80dd2ffb6ce | |
parent | f130d846bc52caddbbc35ead7b18772a10ee0141 (diff) | |
download | tuna-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-x | tuna/gui/procview.py | 72 | ||||
-rwxr-xr-x | tuna/tuna_gui.py | 7 |
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): |