This patch adds the ability for the oprofile collector to monitor multiple event counters. This will be useful in computing estimates of percentage of CPU cycles spent servicing TLB misses, ratios of TLB misses to CPU cycles spent or instructions retired, etc.
Signed-off-by: Eric B Munson <[email protected]> --- TLBC/OpCollect.pm | 97 ++++++++++++++++++++++++++++++++++++++++++----------- cpupcstat | 10 +++--- 2 files changed, 82 insertions(+), 25 deletions(-) diff --git a/TLBC/OpCollect.pm b/TLBC/OpCollect.pm index 3dea7c8..d0d071f 100644 --- a/TLBC/OpCollect.pm +++ b/TLBC/OpCollect.pm @@ -18,8 +18,9 @@ use TLBC::DataCollect; our @ISA = qw(TLBC::DataCollect); -my $count = 0; my $reference; +my (%event_map, %lowlevel); +my (%event_col_map, %event_name); #use interface 'DataCollect'; @@ -33,31 +34,33 @@ sub _clear_oprofile() return $self; } -sub _setup_oprofile() -{ - my $self = shift; - my $vmlinux = shift; - my $event = shift; - my $cmd = "$Bin/oprofile_start.sh --vmlinux=$vmlinux " . - "--event=$event > /dev/null 2>&1"; - system($cmd) == 0 or return 0; - return $self; -} - sub _get_event() { my $self = shift; my $event = shift; - my @vals; my $lowlevel_event; + $lowlevel_event = `$Bin/oprofile_map_events.pl --event $event 2>/dev/null`; chomp($lowlevel_event); if ($lowlevel_event eq "" || $lowlevel_event !~ /^[A-Z0-9_]+:[0-9]+/) { die "Unable to find $event event for this CPU\n"; } + $event_map{$event} = $lowlevel_event; + return $self; +} - @vals = split(/:/, $lowlevel_event); - $count = $vals[1]; +sub _setup_oprofile() +{ + my $self = shift; + my $vmlinux = shift; + my $refEvents = shift; + my $cmd = "$Bin/oprofile_start.sh --vmlinux=$vmlinux "; + foreach my $event (@{$refEvents}) { + $cmd .= " --event=$event"; + $self->_get_event($event); + } + $cmd .= " > /dev/null 2>&1"; + system($cmd) == 0 or return 0; return $self; } @@ -77,15 +80,55 @@ sub setup() { my $self = shift; my $vmlinux = shift; - my $event = shift; - $self->_get_event($event); + my $refEvents = shift; $self->_clear_oprofile(); - return $self->_setup_oprofile($vmlinux, $event); + return $self->_setup_oprofile($vmlinux, $refEvents); } sub samples() { - return $count; + my $self = shift; + my $event = shift; + my $count = 0; + my $lowlevel; + my @vals; + $lowlevel = $event_map{$event}; + if (!$lowlevel) { + die "Unable to locate count and event for $event for this CPU.\n"; + } + @vals = split(/:/, $lowlevel); + return $vals[1]; +} + +sub _get_column() +{ + my $self = shift; + my $report = shift; + my $event = shift; + my @results; + my $line; + my $col = $event_col_map{$event}; + + if ($col) { + return $col; + } + + @results = split(/\n/, $report); + foreach $line (@results) { + if ($line =~ /$event.*\|/) { + my @vals = split(/\|/, $line); + my $size = @vals; + + for (my $i = 0; $i < $size; $i++) { + if ($vals[$i] =~ /$event/) { + $event_col_map{$event} = $i; + return $i; + } + } + die "Unable to find event column.\n"; + } + } + die "Unable to find column labels.\n"; } sub get_current_eventcount() @@ -96,17 +139,31 @@ sub get_current_eventcount() my $hits = 0; my $self = shift; my $binName = shift; + my $event = shift; + my $col = 0; + my $lowlevel = $event_map{$event}; + if (!$lowlevel) { + die "Unable to locate event for $event for this CPU.\n"; + } + my @vals = split(/:/, $lowlevel); + $event = $vals[0]; + # The event column in opreport only uses the first 12 letters of + # the event name + $event = substr($event, 0, 12); system("opcontrol --dump > /dev/null 2>&1"); $report = `opreport`; @results = split(/\n/, $report); + $col = $self->_get_column($report, $event); + foreach $line (@results) { if ($line =~ /$binName/) { chomp($line); $line =~ s/^\s+//; $line =~ s/\s+$//; + $line =~ s/\s+/ /g; my @vals = split(/ /, $line); - $hits += $vals[0]; + $hits += $vals[$col * 2]; } } return $hits; diff --git a/cpupcstat b/cpupcstat index f6d5ef2..9b810fd 100755 --- a/cpupcstat +++ b/cpupcstat @@ -89,19 +89,19 @@ sub run_profile() printf("%20s%20s%24s\n", "Target Name", "DTLB Miss Samples", "Samples/second"); - printf("%20s%20s%24s\n", "", "Sample every " . $collector->samples(), ""); + printf("%20s%20s%24s\n", "", "Sample every " . $collector->samples("dtlb_miss"), ""); sleep($wait_time); # While our target is still running and we have not exceeded our # runtime, collect oprofile data every $wait_time seconds to display # the dtlb miss rate. while (waitpid($pid, WNOHANG) <= 0 || $persist) { - $ret = $collector->get_current_eventcount($binName); + $ret = $collector->get_current_eventcount($binName, "dtlb_miss"); $new = $ret - $prev; printf("%20s%20d%24f\n", $binName, $new, $new / $wait_time); $prev = $ret; if ($kernel) { - $ret = $collector->get_current_eventcount("vmlinux"); + $ret = $collector->get_current_eventcount("vmlinux", "dtlb_miss"); $new = $ret - $kern_prev; printf("%20s%20d%24f\n", "vmlinux", $new, $new / $wait_time); @@ -116,9 +116,9 @@ sub run_profile() } $end_time = time(); $time_elapsed = $end_time - $start_time; - $misses = $collector->get_current_eventcount($binName); + $misses = $collector->get_current_eventcount($binName, "dtlb_miss"); if ($kernel) { - $kern_misses = $collector->get_current_eventcount("vmlinux"); + $kern_misses = $collector->get_current_eventcount("vmlinux", "dtlb_miss"); } $collector->shutdown(); -- 1.6.3.3 ------------------------------------------------------------------------------ This SF.Net email is sponsored by the Verizon Developer Community Take advantage of Verizon's best-in-class app development support A streamlined, 14 day to market process makes app distribution fast and easy Join now and get one step closer to millions of Verizon customers http://p.sf.net/sfu/verizon-dev2dev _______________________________________________ Libhugetlbfs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/libhugetlbfs-devel
