2015-01-15 02:44:54 +03:00
|
|
|
#!/bin/bash
|
|
|
|
|
#
|
|
|
|
|
# Poor man's sampling profiler for NuttX.
|
|
|
|
|
#
|
|
|
|
|
# The stack folding script was inspired by stackcollapse-gdb.pl from the FlameGraph project.
|
|
|
|
|
#
|
|
|
|
|
# Usage: Install flamegraph.pl in your PATH, define the variables below, configure your .gdbinit, run the script and go
|
|
|
|
|
# have a coffee. When you're back, you'll see the flamegraph. Note that frequent calls to GDB significantly
|
|
|
|
|
# interfere with normal operation of the target, which means that you can't profile real-time tasks with it.
|
|
|
|
|
#
|
|
|
|
|
# Requirements: ARM GDB with Python support
|
|
|
|
|
#
|
|
|
|
|
|
2015-01-16 20:47:29 +03:00
|
|
|
set -e
|
2015-01-15 02:44:54 +03:00
|
|
|
root=$(dirname $0)/..
|
|
|
|
|
|
2015-01-16 20:47:29 +03:00
|
|
|
#
|
|
|
|
|
# Parsing the arguments. Read this section for usage info.
|
|
|
|
|
#
|
|
|
|
|
nsamples=0
|
|
|
|
|
sleeptime=0.1 # Doctors recommend 7-8 hours a day
|
|
|
|
|
taskname=
|
|
|
|
|
elf=$root/Build/px4fmu-v2_default.build/firmware.elf
|
|
|
|
|
append=0
|
|
|
|
|
fgfontsize=5
|
|
|
|
|
fgwidth=1900
|
2015-01-15 02:44:54 +03:00
|
|
|
|
2015-01-16 20:47:29 +03:00
|
|
|
function usage()
|
|
|
|
|
{
|
|
|
|
|
echo "Invalid usage. Supported options:"
|
|
|
|
|
cat $0 | sed -n 's/^\s*--\([^)\*]*\).*/\1/p' # Don't try this at home.
|
|
|
|
|
exit 1
|
|
|
|
|
}
|
2015-01-15 02:44:54 +03:00
|
|
|
|
2015-01-16 20:47:29 +03:00
|
|
|
for i in "$@"
|
|
|
|
|
do
|
|
|
|
|
case $i in
|
|
|
|
|
--nsamples=*)
|
|
|
|
|
nsamples="${i#*=}"
|
|
|
|
|
;;
|
|
|
|
|
--sleeptime=*)
|
|
|
|
|
sleeptime="${i#*=}"
|
|
|
|
|
;;
|
|
|
|
|
--taskname=*)
|
|
|
|
|
taskname="${i#*=}"
|
|
|
|
|
;;
|
|
|
|
|
--elf=*)
|
|
|
|
|
elf="${i#*=}"
|
|
|
|
|
;;
|
|
|
|
|
--append)
|
|
|
|
|
append=1
|
|
|
|
|
;;
|
|
|
|
|
--fgfontsize=*)
|
|
|
|
|
fgfontsize="${i#*=}"
|
|
|
|
|
;;
|
|
|
|
|
--fgwidth=*)
|
|
|
|
|
fgwidth="${i#*=}"
|
|
|
|
|
;;
|
|
|
|
|
*)
|
|
|
|
|
usage
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
shift
|
|
|
|
|
done
|
2015-01-15 02:44:54 +03:00
|
|
|
|
2015-01-16 20:47:29 +03:00
|
|
|
#
|
|
|
|
|
# Temporary files
|
|
|
|
|
#
|
|
|
|
|
stacksfile=/tmp/pmpn-stacks.log
|
|
|
|
|
foldfile=/tmp/pmpn-folded.txt
|
|
|
|
|
graphfile=/tmp/pmpn-flamegraph.svg
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
|
# Sampling if requested. Note that if $append is true, the stack file will not be rewritten.
|
|
|
|
|
#
|
2015-01-15 02:44:54 +03:00
|
|
|
cd $root
|
|
|
|
|
|
2015-01-16 20:47:29 +03:00
|
|
|
if [[ $nsamples > 0 && "$taskname" != "" ]]
|
|
|
|
|
then
|
|
|
|
|
[[ $append = 0 ]] && (rm -f $stacksfile; echo "Old stacks removed")
|
2015-01-15 02:44:54 +03:00
|
|
|
|
2015-01-16 20:47:29 +03:00
|
|
|
echo "Sampling..."
|
2015-01-15 02:44:54 +03:00
|
|
|
|
2015-01-16 20:47:29 +03:00
|
|
|
for x in $(seq 1 $nsamples)
|
|
|
|
|
do
|
|
|
|
|
arm-none-eabi-gdb $exe --batch -ex "set print asm-demangle on" \
|
|
|
|
|
-ex "source $root/Debug/Nuttx.py" \
|
|
|
|
|
-ex "show mybt $taskname" \
|
|
|
|
|
2> /dev/null \
|
|
|
|
|
| sed -n 's/0\.0:\(#.*\)/\1/p' \
|
|
|
|
|
>> $stacksfile
|
|
|
|
|
echo -e '\n\n' >> $stacksfile
|
|
|
|
|
echo -ne "\r$x/$nsamples"
|
|
|
|
|
sleep $sleeptime
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
echo
|
|
|
|
|
echo "Stacks saved to $stacksfile"
|
|
|
|
|
else
|
|
|
|
|
echo "Sampling skipped - set 'nsamples' and 'taskname' to re-sample."
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
|
# Folding the stacks.
|
|
|
|
|
#
|
|
|
|
|
if [ ! -f $stacksfile ]; then
|
|
|
|
|
echo "Where are the stack samples?"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
cat $stacksfile | perl -e 'use File::Basename;
|
|
|
|
|
my $current = "";
|
2015-01-15 02:44:54 +03:00
|
|
|
my %stacks;
|
|
|
|
|
while(<>) {
|
2015-01-16 20:47:29 +03:00
|
|
|
if(m/^#[0-9]*\s*0x[a-zA-Z0-9]*\s*in (.*) at (.*)/) {
|
|
|
|
|
my $x = $1 eq "None" ? basename($2) : $1;
|
|
|
|
|
if ($current eq "") { $current = $x; }
|
|
|
|
|
else { $current = $x . ";" . $current; }
|
2015-01-15 02:44:54 +03:00
|
|
|
} elsif(!($current eq "")) {
|
|
|
|
|
$stacks{$current} += 1;
|
|
|
|
|
$current = "";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
foreach my $k (sort { $a cmp $b } keys %stacks) {
|
|
|
|
|
print "$k $stacks{$k}\n";
|
2015-01-16 20:47:29 +03:00
|
|
|
}' > $foldfile
|
2015-01-15 02:44:54 +03:00
|
|
|
|
2015-01-16 20:47:29 +03:00
|
|
|
echo "Folded stacks saved to $foldfile"
|
2015-01-15 02:44:54 +03:00
|
|
|
|
2015-01-16 20:47:29 +03:00
|
|
|
#
|
|
|
|
|
# Graphing.
|
|
|
|
|
#
|
|
|
|
|
cat $foldfile | flamegraph.pl --fontsize=$fgfontsize --width=$fgwidth > $graphfile
|
|
|
|
|
xdg-open $graphfile
|