From 22f971e83eddada009053d964a397550807b9b50 Mon Sep 17 00:00:00 2001 From: William Cohen Date: Mon, 9 Feb 2009 10:12:00 -0500 Subject: Revised version of kmalloc-top in systemtap.examples. --- testsuite/systemtap.examples/memory/kmalloc-top | 171 +++++++++++++++++++++ .../systemtap.examples/memory/kmalloc-top.meta | 13 ++ 2 files changed, 184 insertions(+) create mode 100755 testsuite/systemtap.examples/memory/kmalloc-top create mode 100644 testsuite/systemtap.examples/memory/kmalloc-top.meta (limited to 'testsuite/systemtap.examples/memory') diff --git a/testsuite/systemtap.examples/memory/kmalloc-top b/testsuite/systemtap.examples/memory/kmalloc-top new file mode 100755 index 00000000..ccce0c17 --- /dev/null +++ b/testsuite/systemtap.examples/memory/kmalloc-top @@ -0,0 +1,171 @@ +#!/usr/bin/perl +# +# This script accumulates the execution paths of all calls to kmalloc +# in the kernel. On Ctrl-C (or exit of the command provided by -c option), +# it sorts, filters and displays them on +# stdout. +# +# The -e (exclude) option can be used to specify a comma-separated list +# - any stack with contents matching any of the items in the list will +# be excluded from the output. +# +# The -m (min) option can be used to specify the minimum number of +# occurrences a stack needs to be included in the output. +# +# The -t (top) option can be used to specify printing only the +# top N stack traces. +# +# The -c (command) option runs starts the command and script +# only runs for the duration of the command. +# +# The -o (options) option passes the options to systemap. +# +# Usage: ./kmalloc-top [-m min] [-e exclude list] [-t top_n] [-c command] +# [-o options] +# Ctrl-c + +use Getopt::Std; + +my $kmalloc_stacks; +my $total_kmallocs; +my $filtered_kmallocs; +my $sorted_stacks; +my $first_n = 1000000000; +my $min_count = 1; +my $exclude; +my $options; + +$SIG{INT} = \&sigint_handler; + +getopts('c:e:m:t:o:'); + +if ($opt_e) { + $exclude = join('|', split(/,/, $opt_e)); + print "Will exclude stacks containing: $exclude\n"; +} + +if ($opt_t) { + $first_n = $opt_t; + print "Will print only the top $first_n stacks.\n"; +} + +if ($opt_m) { + $min_count = $opt_m; +} + +if ($opt_c) { + $command="-c \"$opt_c\"" +} + +if ($opt_o) { + $options=$opt_o +} + +print "Will print stacks with counts >= $min_count.\n"; +print STDERR "Press Ctrl-C to stop.\n"; + +#The systemtap script that instruments the kmalloc +$script=" +global kmalloc_stack + +probe kernel.function(\"__kmalloc\") { kmalloc_stack[backtrace()]++ } + +probe timer.ms(100), end +{ + foreach (stack in kmalloc_stack) { + printf(\"\\n\") + print_stack(stack) + printf(\"\\n\") + printf(\"%d\\n\", kmalloc_stack[stack]) + } + delete kmalloc_stack +} +"; + +open STREAM, "stap $options -e '$script' $command|" or die "Couldn't get output stream $!"; + +while () { + if (/(.*?)<\/hashval>/) { + update_hash($key, $1); + $key = ""; + } elsif ($_ !~ (/|<\/hashkey>/)) { + $key .= $_; + } +} + +$num_keys_before_filtering = scalar keys %kmalloc_stacks; +$total_kmallocs = count_kmallocs(); +filter_stacks(); +sort_stacks(); +top_stacks(); +sort_stacks(); +$num_keys_after_filtering = scalar keys %kmalloc_stacks; +$filtered_kmallocs = count_kmallocs(); +summarize(); +exit(); + +sub update_hash +{ + my($key, $val) = @_; + $kmalloc_stacks{$key} += $val; +} + +sub filter_stacks +{ + while (($stack, $count) = each %kmalloc_stacks) { + if ($count < $min_count) { + delete $kmalloc_stacks{$stack}; + } elsif ($exclude && $stack =~ /$exclude/) { + delete $kmalloc_stacks{$stack}; + } + } +} + +sub top_stacks +{ + $count=0; + foreach $stack(@sorted_stacks) { + $count+=1; + if ($count > $first_n) { + delete $kmalloc_stacks{$stack}; + } + } +} + +sub sort_stacks +{ + @sorted_stacks = sort { $kmalloc_stacks{$b} <=> $kmalloc_stacks{$a} } keys %kmalloc_stacks; +} + +sub count_kmallocs { + $count = 0; + foreach $stack(%kmalloc_stacks) { + $count += $kmalloc_stacks{$stack}; + } + return $count; +} + +sub summarize { + print "\n"; + foreach $stack(@sorted_stacks) { + print "This path seen $kmalloc_stacks{$stack} times:\n$stack\n"; + } + + if ($total_kmallocs > 0) { + $percent = ($filtered_kmallocs)*100/$total_kmallocs; + } else { + $percent = 0; + } + print "Num stacks before filtering: $num_keys_before_filtering\n"; + print "Num stacks after filtering: $num_keys_after_filtering\n"; + print "Total kmallocs (before filtering): $total_kmallocs\n"; + print "Total kmallocs (after filtering): $filtered_kmallocs\n"; + print "The filter stacks have $percent of the total kmallocs\n"; + + close(STREAM); +} + +sub sigint_handler +{ + system("pkill kmalloc-stacks"); +} diff --git a/testsuite/systemtap.examples/memory/kmalloc-top.meta b/testsuite/systemtap.examples/memory/kmalloc-top.meta new file mode 100644 index 00000000..2dfbf898 --- /dev/null +++ b/testsuite/systemtap.examples/memory/kmalloc-top.meta @@ -0,0 +1,13 @@ +title: Show Paths to Kernel Malloc (kmalloc) Invocations +name: kmalloc-top +version: 1.0 +author: anonymous +keywords: memory +subsystem: memory +status: production +exit: user-controlled +output: sorted-list +scope: system-wide +description: The kmalloc-top perl program runs a small systemtap script to collect stack traces for each call to the kmalloc function and counts the time that each stack trace is observed. When kmalloc-top exits it prints out sorted list. The output can be be filtered to print only only the first stack traces (-t) stack traces with more a minimum counts (-m), or exclude certain stack traces (-e). +test_check: kmalloc-top -o "-p4" -c "sleep 0" +test_installcheck: kmalloc-top -c "sleep 1" -- cgit From 413996e0c3b55047e12272678627f7833228d892 Mon Sep 17 00:00:00 2001 From: William Cohen Date: Thu, 12 Feb 2009 15:58:24 -0500 Subject: Function to determine page fault type and have pfaults.stp exercise it. --- testsuite/systemtap.examples/memory/pfaults.meta | 13 +++++++++ testsuite/systemtap.examples/memory/pfaults.stp | 35 ++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 testsuite/systemtap.examples/memory/pfaults.meta create mode 100644 testsuite/systemtap.examples/memory/pfaults.stp (limited to 'testsuite/systemtap.examples/memory') diff --git a/testsuite/systemtap.examples/memory/pfaults.meta b/testsuite/systemtap.examples/memory/pfaults.meta new file mode 100644 index 00000000..149d83fa --- /dev/null +++ b/testsuite/systemtap.examples/memory/pfaults.meta @@ -0,0 +1,13 @@ +title: Generate Log of Major and Minor Page Faults +name: pfaults.stp +version: 1.0 +author: anonymous +keywords: memory +subsystem: memory +status: production +exit: user-controlled +output: sorted-list +scope: system-wide +description: The pfaults.stp script generates a simple log for each major and minor page fault that occurs on the system. Each line contains a timestamp (in microseconds) when the page fault servicing was completed, the pid of the process, the address of the page fault, the type of access (read or write), the type of fault (major or minor), and the elapsed time for page fault. This log can be examined to determine where the page faults are occuring. +test_check: stap -p4 pfaults.stp +test_installcheck: stap pfaults.stp -c "sleep 1" diff --git a/testsuite/systemtap.examples/memory/pfaults.stp b/testsuite/systemtap.examples/memory/pfaults.stp new file mode 100644 index 00000000..5bf1a8a6 --- /dev/null +++ b/testsuite/systemtap.examples/memory/pfaults.stp @@ -0,0 +1,35 @@ +#! /usr/bin/env stap + +global fault_entry_time, fault_address, fault_access +global time_offset + +probe begin { time_offset = gettimeofday_us() } + +probe vm.pagefault { + t = gettimeofday_us() + p = pid() + fault_entry_time[p] = t + fault_address[p] = address + fault_access[p] = write_access ? "w" : "r" +} + +probe vm.pagefault.return { + t=gettimeofday_us() + p = pid() + if (!(p in fault_entry_time)) next + e = t - fault_entry_time[p] + if (vm_fault_contains(fault_type,VM_FAULT_MINOR)) { + ftype="minor" + } else if (vm_fault_contains(fault_type,VM_FAULT_MAJOR)) { + ftype="major" + } else { + next #only want to deal with minor and major page faults + } + + printf("%d:%d:%p:%s:%s:%d\n", + t - time_offset, p, fault_address[p], fault_access[p], ftype, e) + #free up memory + delete fault_entry_time[p] + delete fault_address[p] + delete fault_access[p] +} -- cgit From 57439678db34719d2795e84cbe1bb9ef2b537deb Mon Sep 17 00:00:00 2001 From: William Cohen Date: Thu, 12 Feb 2009 23:08:21 -0500 Subject: Correct entries for test_check and test_installcheck. --- testsuite/systemtap.examples/memory/kmalloc-top.meta | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'testsuite/systemtap.examples/memory') diff --git a/testsuite/systemtap.examples/memory/kmalloc-top.meta b/testsuite/systemtap.examples/memory/kmalloc-top.meta index 2dfbf898..93308909 100644 --- a/testsuite/systemtap.examples/memory/kmalloc-top.meta +++ b/testsuite/systemtap.examples/memory/kmalloc-top.meta @@ -9,5 +9,5 @@ exit: user-controlled output: sorted-list scope: system-wide description: The kmalloc-top perl program runs a small systemtap script to collect stack traces for each call to the kmalloc function and counts the time that each stack trace is observed. When kmalloc-top exits it prints out sorted list. The output can be be filtered to print only only the first stack traces (-t) stack traces with more a minimum counts (-m), or exclude certain stack traces (-e). -test_check: kmalloc-top -o "-p4" -c "sleep 0" -test_installcheck: kmalloc-top -c "sleep 1" +test_check: ./kmalloc-top -o "-p4" -c "sleep 0" +test_installcheck: ./kmalloc-top -c "sleep 1" -- cgit