mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 19:29:37 +00:00
![Thomas Gleixner](/assets/img/avatar_default.png)
Based on 1 normalized pattern(s): this software is licensed under the terms of the gnu general public license version 2 as published by the free software foundation and may be copied distributed and modified under those terms this program is distributed in the hope that it will be useful but without any warranty without even the implied warranty of merchantability or fitness for a particular purpose see the gnu general public license for more details extracted by the scancode license scanner the SPDX license identifier GPL-2.0-only has been chosen to replace the boilerplate/reference in 285 file(s). Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Alexios Zavras <alexios.zavras@intel.com> Reviewed-by: Allison Randal <allison@lohutok.net> Cc: linux-spdx@vger.kernel.org Link: https://lkml.kernel.org/r/20190529141900.642774971@linutronix.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
268 lines
4.7 KiB
Bash
268 lines
4.7 KiB
Bash
#!/bin/bash
|
|
# SPDX-License-Identifier: GPL-2.0-only
|
|
|
|
# Sergey Senozhatsky, 2015
|
|
# sergey.senozhatsky.work@gmail.com
|
|
#
|
|
|
|
|
|
# This program is intended to plot a `slabinfo -X' stats, collected,
|
|
# for example, using the following command:
|
|
# while [ 1 ]; do slabinfo -X >> stats; sleep 1; done
|
|
#
|
|
# Use `slabinfo-gnuplot.sh stats' to pre-process collected records
|
|
# and generate graphs (totals, slabs sorted by size, slabs sorted
|
|
# by size).
|
|
#
|
|
# Graphs can be [individually] regenerate with different ranges and
|
|
# size (-r %d,%d and -s %d,%d options).
|
|
#
|
|
# To visually compare N `totals' graphs, do
|
|
# slabinfo-gnuplot.sh -t FILE1-totals FILE2-totals ... FILEN-totals
|
|
#
|
|
|
|
min_slab_name_size=11
|
|
xmin=0
|
|
xmax=0
|
|
width=1500
|
|
height=700
|
|
mode=preprocess
|
|
|
|
usage()
|
|
{
|
|
echo "Usage: [-s W,H] [-r MIN,MAX] [-t|-l] FILE1 [FILE2 ..]"
|
|
echo "FILEs must contain 'slabinfo -X' samples"
|
|
echo "-t - plot totals for FILE(s)"
|
|
echo "-l - plot slabs stats for FILE(s)"
|
|
echo "-s %d,%d - set image width and height"
|
|
echo "-r %d,%d - use data samples from a given range"
|
|
}
|
|
|
|
check_file_exist()
|
|
{
|
|
if [ ! -f "$1" ]; then
|
|
echo "File '$1' does not exist"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
do_slabs_plotting()
|
|
{
|
|
local file=$1
|
|
local out_file
|
|
local range="every ::$xmin"
|
|
local xtic=""
|
|
local xtic_rotate="norotate"
|
|
local lines=2000000
|
|
local wc_lines
|
|
|
|
check_file_exist "$file"
|
|
|
|
out_file=`basename "$file"`
|
|
if [ $xmax -ne 0 ]; then
|
|
range="$range::$xmax"
|
|
lines=$((xmax-xmin))
|
|
fi
|
|
|
|
wc_lines=`cat "$file" | wc -l`
|
|
if [ $? -ne 0 ] || [ "$wc_lines" -eq 0 ] ; then
|
|
wc_lines=$lines
|
|
fi
|
|
|
|
if [ "$wc_lines" -lt "$lines" ]; then
|
|
lines=$wc_lines
|
|
fi
|
|
|
|
if [ $((width / lines)) -gt $min_slab_name_size ]; then
|
|
xtic=":xtic(1)"
|
|
xtic_rotate=90
|
|
fi
|
|
|
|
gnuplot -p << EOF
|
|
#!/usr/bin/env gnuplot
|
|
|
|
set terminal png enhanced size $width,$height large
|
|
set output '$out_file.png'
|
|
set autoscale xy
|
|
set xlabel 'samples'
|
|
set ylabel 'bytes'
|
|
set style histogram columnstacked title textcolor lt -1
|
|
set style fill solid 0.15
|
|
set xtics rotate $xtic_rotate
|
|
set key left above Left title reverse
|
|
|
|
plot "$file" $range u 2$xtic title 'SIZE' with boxes,\
|
|
'' $range u 3 title 'LOSS' with boxes
|
|
EOF
|
|
|
|
if [ $? -eq 0 ]; then
|
|
echo "$out_file.png"
|
|
fi
|
|
}
|
|
|
|
do_totals_plotting()
|
|
{
|
|
local gnuplot_cmd=""
|
|
local range="every ::$xmin"
|
|
local file=""
|
|
|
|
if [ $xmax -ne 0 ]; then
|
|
range="$range::$xmax"
|
|
fi
|
|
|
|
for i in "${t_files[@]}"; do
|
|
check_file_exist "$i"
|
|
|
|
file="$file"`basename "$i"`
|
|
gnuplot_cmd="$gnuplot_cmd '$i' $range using 1 title\
|
|
'$i Memory usage' with lines,"
|
|
gnuplot_cmd="$gnuplot_cmd '' $range using 2 title \
|
|
'$i Loss' with lines,"
|
|
done
|
|
|
|
gnuplot -p << EOF
|
|
#!/usr/bin/env gnuplot
|
|
|
|
set terminal png enhanced size $width,$height large
|
|
set autoscale xy
|
|
set output '$file.png'
|
|
set xlabel 'samples'
|
|
set ylabel 'bytes'
|
|
set key left above Left title reverse
|
|
|
|
plot $gnuplot_cmd
|
|
EOF
|
|
|
|
if [ $? -eq 0 ]; then
|
|
echo "$file.png"
|
|
fi
|
|
}
|
|
|
|
do_preprocess()
|
|
{
|
|
local out
|
|
local lines
|
|
local in=$1
|
|
|
|
check_file_exist "$in"
|
|
|
|
# use only 'TOP' slab (biggest memory usage or loss)
|
|
let lines=3
|
|
out=`basename "$in"`"-slabs-by-loss"
|
|
`cat "$in" | grep -A "$lines" 'Slabs sorted by loss' |\
|
|
egrep -iv '\-\-|Name|Slabs'\
|
|
| awk '{print $1" "$4+$2*$3" "$4}' > "$out"`
|
|
if [ $? -eq 0 ]; then
|
|
do_slabs_plotting "$out"
|
|
fi
|
|
|
|
let lines=3
|
|
out=`basename "$in"`"-slabs-by-size"
|
|
`cat "$in" | grep -A "$lines" 'Slabs sorted by size' |\
|
|
egrep -iv '\-\-|Name|Slabs'\
|
|
| awk '{print $1" "$4" "$4-$2*$3}' > "$out"`
|
|
if [ $? -eq 0 ]; then
|
|
do_slabs_plotting "$out"
|
|
fi
|
|
|
|
out=`basename "$in"`"-totals"
|
|
`cat "$in" | grep "Memory used" |\
|
|
awk '{print $3" "$7}' > "$out"`
|
|
if [ $? -eq 0 ]; then
|
|
t_files[0]=$out
|
|
do_totals_plotting
|
|
fi
|
|
}
|
|
|
|
parse_opts()
|
|
{
|
|
local opt
|
|
|
|
while getopts "tlr::s::h" opt; do
|
|
case $opt in
|
|
t)
|
|
mode=totals
|
|
;;
|
|
l)
|
|
mode=slabs
|
|
;;
|
|
s)
|
|
array=(${OPTARG//,/ })
|
|
width=${array[0]}
|
|
height=${array[1]}
|
|
;;
|
|
r)
|
|
array=(${OPTARG//,/ })
|
|
xmin=${array[0]}
|
|
xmax=${array[1]}
|
|
;;
|
|
h)
|
|
usage
|
|
exit 0
|
|
;;
|
|
\?)
|
|
echo "Invalid option: -$OPTARG" >&2
|
|
exit 1
|
|
;;
|
|
:)
|
|
echo "-$OPTARG requires an argument." >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
return $OPTIND
|
|
}
|
|
|
|
parse_args()
|
|
{
|
|
local idx=0
|
|
local p
|
|
|
|
for p in "$@"; do
|
|
case $mode in
|
|
preprocess)
|
|
files[$idx]=$p
|
|
idx=$idx+1
|
|
;;
|
|
totals)
|
|
t_files[$idx]=$p
|
|
idx=$idx+1
|
|
;;
|
|
slabs)
|
|
files[$idx]=$p
|
|
idx=$idx+1
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
parse_opts "$@"
|
|
argstart=$?
|
|
parse_args "${@:$argstart}"
|
|
|
|
if [ ${#files[@]} -eq 0 ] && [ ${#t_files[@]} -eq 0 ]; then
|
|
usage
|
|
exit 1
|
|
fi
|
|
|
|
case $mode in
|
|
preprocess)
|
|
for i in "${files[@]}"; do
|
|
do_preprocess "$i"
|
|
done
|
|
;;
|
|
totals)
|
|
do_totals_plotting
|
|
;;
|
|
slabs)
|
|
for i in "${files[@]}"; do
|
|
do_slabs_plotting "$i"
|
|
done
|
|
;;
|
|
*)
|
|
echo "Unknown mode $mode" >&2
|
|
usage
|
|
exit 1
|
|
;;
|
|
esac
|