Date: 26 May 2002 02:12:11 +0200 From: Dag-Erling Smorgrav <des@ofug.org> To: current@freebsd.org Subject: Mutex statistics script Message-ID: <xzpit5b938k.fsf@flood.ping.uio.no>
next in thread | raw e-mail | index | archive | help
[-- Attachment #1 --]
The -g option causes the script to strip off the source file and line
and accumulate totals for each mutex. The -r option reverses the
sorting order. The (mutually exclusive) -a, -c, -m and -t options
sort the results by the max, total, count or average column.
Here's a list of the ten most frequently acquired mutices (over a
period of 11 days), grouped by mutex name:
des@des ~% mtxstat -gcr -l 10
max total count average name
1077094 3634841194 3021298899 1 process lock
200760 4475449899 2339885146 2 pool mutex
11075293 54743743699 2127442731 26 Giant
252 2151217659 1587924805 1 sellck
24594 1913632993 813816142 2 vnode interlock
442810 12872182712 716587273 18 filedesc structure
520 2038681691 480818216 4 PCPU 16
36114 156710765 187686674 0 bio queue
114 270322499 185453842 1 malloc
87 165913390 182277045 1 temp
Sorted by total time held, a few minutes later:
des@des ~% mtxstat -gtr -l 10
max total count average name
11075293 54762076072 2128355890 26 Giant
442810 12881479450 716922166 18 filedesc structure
200760 4475944044 2340324507 2 pool mutex
97625 4303676900 51655812 83 mntvnode
1077094 3636650031 3022817522 1 process lock
252 2152670298 1589143889 1 sellck
520 2038861358 480872541 4 PCPU 16
24594 1913699459 813846649 2 vnode interlock
8418 383692889 9040940 42 xl0
87 348538260 74251990 5 vnode_free_list
IWBNI there was a way to record how many times each mutex was
contested...
DES
--
Dag-Erling Smorgrav - des@ofug.org
[-- Attachment #2 --]
#!/usr/bin/perl -Tw
#-
# Copyright (c) 2002 Dag-Erling Coïdan Smørgrav
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer
# in this position and unchanged.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# $Id$
#
use strict;
use Getopt::Std;
sub usage() {
print(STDERR "usage: mtxstat [-gr] [-a|c|m|t] [-l limit]\n");
exit(1);
}
MAIN:{
my %opts; # Command-line options
my $key; # Sort key
my $limit; # Output limit
local *PIPE; # Pipe
my $header; # Header line
my @names; # Field names
my %data; # Mutex data
my @list; # List of entries
getopts("acgl:mrt", \%opts)
or usage();
if ($opts{'a'}) {
usage()
if ($opts{'c'} || $opts{'m'} || $opts{'t'});
$key = 'average';
} elsif ($opts{'c'}) {
usage()
if ($opts{'m'} || $opts{'t'});
$key = 'count';
} elsif ($opts{'m'}) {
usage()
if ($opts{'t'});
$key = 'max';
} elsif ($opts{'t'}) {
$key = 'total';
}
if ($opts{'l'}) {
if ($opts{'l'} !~ m/^\d+$/) {
usage();
}
$limit = $opts{'l'};
}
$ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/sbin';
open(PIPE, "sysctl -n debug.mutex.prof.stats|")
or die("open(): $!\n");
$header = <PIPE>;
chomp($header);
@names = split(' ', $header);
if (defined($key) && !grep(/^$key$/, @names)) {
die("can't find sort key '$key' in header\n");
}
while (<PIPE>) {
chomp();
my @fields = split(' ', $_, @names);
next unless @fields;
my %entry;
foreach (@names) {
$entry{$_} = ($_ eq 'name') ? shift(@fields) : 0.0 + shift(@fields);
}
if ($opts{'g'}) {
$entry{'name'} =~ s/^(\S+)\s+\((.*)\)$/$2/;
}
my $name = $entry{'name'};
if ($data{$name}) {
if ($entry{'max'} > $data{$name}->{'max'}) {
$data{$name}->{'max'} = $entry{'max'};
}
$data{$name}->{'total'} += $entry{'total'};
$data{$name}->{'count'} += $entry{'count'};
$data{$name}->{'average'} =
$data{$name}->{'total'} / $data{$name}->{'count'};
} else {
$data{$name} = \%entry;
}
}
if (defined($key)) {
@list = sort({ $data{$a}->{$key} <=> $data{$b}->{$key} }
sort(keys(%data)));
} else {
@list = sort(keys(%data));
}
if ($opts{'r'}) {
@list = reverse(@list);
}
print("$header\n");
if ($limit) {
while (@list > $limit) {
pop(@list);
}
}
foreach (@list) {
printf("%12.0f %12.0f %12.0f %12.0f %s\n",
$data{$_}->{'max'},
$data{$_}->{'total'},
$data{$_}->{'count'},
$data{$_}->{'average'},
$data{$_}->{'name'});
}
}
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?xzpit5b938k.fsf>
