summaryrefslogtreecommitdiffstats
path: root/testsuite/systemtap.samples/kmalloc-top
blob: 42a6d152508a2e7f60076825cbb9d53b45568c70 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!/usr/bin/perl
#
# This script accumulates the execution paths of all calls to kmalloc
# in the kernel.  On Ctrl-C, 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.
#
# Usage: ./kmalloc-top [-m min] [-i exclude list]
# Ctrl-c

use Getopt::Std;

my $kmalloc_stacks;
my $total_kmallocs;
my $sorted_stacks;
my $min_count = 1;
my $exclude;

$SIG{INT} = \&sigint_handler;

getopts('e:m:');

if ($opt_e) {
    $exclude = join('|', split(/,/, $opt_e));
    print "Will exclude stacks containing: $exclude\n";
}

if ($opt_m) {
    $min_count = $opt_n;
}
print "Will print stacks with counts >= $min_count.\n";
print STDERR "Press Ctrl-C to stop.\n";

open STREAM, "stap -g kmalloc-stacks.stp |" or die "Couldn't get output stream $!";

while (<STREAM>) {
    if (/<hashval>(.*?)<\/hashval>/) {
	update_hash($key, $1);
	$key = "";
    } elsif ($_ !~ (/<hashkey>|<\/hashkey>/))  {
	$key .= $_;
    }
}

$num_keys_before_filtering = scalar keys %kmalloc_stacks;
filter_stacks();
$num_keys_after_filtering = scalar keys %kmalloc_stacks;
sort_stacks();
summarize();
exit();

sub update_hash
{
    my($key, $val) = @_;
    $kmalloc_stacks{$key} += $val;
    $total_kmallocs += $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 sort_stacks
{
    @sorted_stacks = sort { $kmalloc_stacks{$b} <=> $kmalloc_stacks{$a} } keys %kmalloc_stacks;
}

sub summarize {
    print "\n";
    foreach $stack(@sorted_stacks) {
	print "This path seen $kmalloc_stacks{$stack} times:\n$stack\n";
    }

    print "Total kmallocs (before filtering): $total_kmallocs\n";
    print "Num stacks before filtering: $num_keys_before_filtering\n";
    print "Num stacks after filtering: $num_keys_after_filtering\n";

    close(STREAM);
}

sub sigint_handler
{
    system("pkill kmalloc-stacks");
}