Back to home page

OSCL-LXR

 
 

    


0001 #!/bin/bash
0002 # SPDX-License-Identifier: GPL-2.0-only
0003 
0004 # Sergey Senozhatsky, 2015
0005 # sergey.senozhatsky.work@gmail.com
0006 #
0007 
0008 
0009 # This program is intended to plot a `slabinfo -X' stats, collected,
0010 # for example, using the following command:
0011 #   while [ 1 ]; do slabinfo -X >> stats; sleep 1; done
0012 #
0013 # Use `slabinfo-gnuplot.sh stats' to pre-process collected records
0014 # and generate graphs (totals, slabs sorted by size, slabs sorted
0015 # by size).
0016 #
0017 # Graphs can be [individually] regenerate with different ranges and
0018 # size (-r %d,%d and -s %d,%d options).
0019 #
0020 # To visually compare N `totals' graphs, do
0021 # slabinfo-gnuplot.sh -t FILE1-totals FILE2-totals ... FILEN-totals
0022 #
0023 
0024 min_slab_name_size=11
0025 xmin=0
0026 xmax=0
0027 width=1500
0028 height=700
0029 mode=preprocess
0030 
0031 usage()
0032 {
0033         echo "Usage: [-s W,H] [-r MIN,MAX] [-t|-l] FILE1 [FILE2 ..]"
0034         echo "FILEs must contain 'slabinfo -X' samples"
0035         echo "-t                        - plot totals for FILE(s)"
0036         echo "-l                        - plot slabs stats for FILE(s)"
0037         echo "-s %d,%d          - set image width and height"
0038         echo "-r %d,%d          - use data samples from a given range"
0039 }
0040 
0041 check_file_exist()
0042 {
0043         if [ ! -f "$1" ]; then
0044                 echo "File '$1' does not exist"
0045                 exit 1
0046         fi
0047 }
0048 
0049 do_slabs_plotting()
0050 {
0051         local file=$1
0052         local out_file
0053         local range="every ::$xmin"
0054         local xtic=""
0055         local xtic_rotate="norotate"
0056         local lines=2000000
0057         local wc_lines
0058 
0059         check_file_exist "$file"
0060 
0061         out_file=`basename "$file"`
0062         if [ $xmax -ne 0 ]; then
0063                 range="$range::$xmax"
0064                 lines=$((xmax-xmin))
0065         fi
0066 
0067         wc_lines=`cat "$file" | wc -l`
0068         if [ $? -ne 0 ] || [ "$wc_lines" -eq 0 ] ; then
0069                 wc_lines=$lines
0070         fi
0071 
0072         if [ "$wc_lines" -lt "$lines" ]; then
0073                 lines=$wc_lines
0074         fi
0075 
0076         if [ $((width / lines)) -gt $min_slab_name_size ]; then
0077                 xtic=":xtic(1)"
0078                 xtic_rotate=90
0079         fi
0080 
0081 gnuplot -p << EOF
0082 #!/usr/bin/env gnuplot
0083 
0084 set terminal png enhanced size $width,$height large
0085 set output '$out_file.png'
0086 set autoscale xy
0087 set xlabel 'samples'
0088 set ylabel 'bytes'
0089 set style histogram columnstacked title textcolor lt -1
0090 set style fill solid 0.15
0091 set xtics rotate $xtic_rotate
0092 set key left above Left title reverse
0093 
0094 plot "$file" $range u 2$xtic title 'SIZE' with boxes,\
0095         '' $range u 3 title 'LOSS' with boxes
0096 EOF
0097 
0098         if [ $? -eq 0 ]; then
0099                 echo "$out_file.png"
0100         fi
0101 }
0102 
0103 do_totals_plotting()
0104 {
0105         local gnuplot_cmd=""
0106         local range="every ::$xmin"
0107         local file=""
0108 
0109         if [ $xmax -ne 0 ]; then
0110                 range="$range::$xmax"
0111         fi
0112 
0113         for i in "${t_files[@]}"; do
0114                 check_file_exist "$i"
0115 
0116                 file="$file"`basename "$i"`
0117                 gnuplot_cmd="$gnuplot_cmd '$i' $range using 1 title\
0118                         '$i Memory usage' with lines,"
0119                 gnuplot_cmd="$gnuplot_cmd '' $range using 2 title \
0120                         '$i Loss' with lines,"
0121         done
0122 
0123 gnuplot -p << EOF
0124 #!/usr/bin/env gnuplot
0125 
0126 set terminal png enhanced size $width,$height large
0127 set autoscale xy
0128 set output '$file.png'
0129 set xlabel 'samples'
0130 set ylabel 'bytes'
0131 set key left above Left title reverse
0132 
0133 plot $gnuplot_cmd
0134 EOF
0135 
0136         if [ $? -eq 0 ]; then
0137                 echo "$file.png"
0138         fi
0139 }
0140 
0141 do_preprocess()
0142 {
0143         local out
0144         local lines
0145         local in=$1
0146 
0147         check_file_exist "$in"
0148 
0149         # use only 'TOP' slab (biggest memory usage or loss)
0150         let lines=3
0151         out=`basename "$in"`"-slabs-by-loss"
0152         `cat "$in" | grep -A "$lines" 'Slabs sorted by loss' |\
0153                 egrep -iv '\-\-|Name|Slabs'\
0154                 | awk '{print $1" "$4+$2*$3" "$4}' > "$out"`
0155         if [ $? -eq 0 ]; then
0156                 do_slabs_plotting "$out"
0157         fi
0158 
0159         let lines=3
0160         out=`basename "$in"`"-slabs-by-size"
0161         `cat "$in" | grep -A "$lines" 'Slabs sorted by size' |\
0162                 egrep -iv '\-\-|Name|Slabs'\
0163                 | awk '{print $1" "$4" "$4-$2*$3}' > "$out"`
0164         if [ $? -eq 0 ]; then
0165                 do_slabs_plotting "$out"
0166         fi
0167 
0168         out=`basename "$in"`"-totals"
0169         `cat "$in" | grep "Memory used" |\
0170                 awk '{print $3" "$7}' > "$out"`
0171         if [ $? -eq 0 ]; then
0172                 t_files[0]=$out
0173                 do_totals_plotting
0174         fi
0175 }
0176 
0177 parse_opts()
0178 {
0179         local opt
0180 
0181         while getopts "tlr::s::h" opt; do
0182                 case $opt in
0183                         t)
0184                                 mode=totals
0185                                 ;;
0186                         l)
0187                                 mode=slabs
0188                                 ;;
0189                         s)
0190                                 array=(${OPTARG//,/ })
0191                                 width=${array[0]}
0192                                 height=${array[1]}
0193                                 ;;
0194                         r)
0195                                 array=(${OPTARG//,/ })
0196                                 xmin=${array[0]}
0197                                 xmax=${array[1]}
0198                                 ;;
0199                         h)
0200                                 usage
0201                                 exit 0
0202                                 ;;
0203                         \?)
0204                                 echo "Invalid option: -$OPTARG" >&2
0205                                 exit 1
0206                                 ;;
0207                         :)
0208                                 echo "-$OPTARG requires an argument." >&2
0209                                 exit 1
0210                                 ;;
0211                 esac
0212         done
0213 
0214         return $OPTIND
0215 }
0216 
0217 parse_args()
0218 {
0219         local idx=0
0220         local p
0221 
0222         for p in "$@"; do
0223                 case $mode in
0224                         preprocess)
0225                                 files[$idx]=$p
0226                                 idx=$idx+1
0227                                 ;;
0228                         totals)
0229                                 t_files[$idx]=$p
0230                                 idx=$idx+1
0231                                 ;;
0232                         slabs)
0233                                 files[$idx]=$p
0234                                 idx=$idx+1
0235                                 ;;
0236                 esac
0237         done
0238 }
0239 
0240 parse_opts "$@"
0241 argstart=$?
0242 parse_args "${@:$argstart}"
0243 
0244 if [ ${#files[@]} -eq 0 ] && [ ${#t_files[@]} -eq 0 ]; then
0245         usage
0246         exit 1
0247 fi
0248 
0249 case $mode in
0250         preprocess)
0251                 for i in "${files[@]}"; do
0252                         do_preprocess "$i"
0253                 done
0254                 ;;
0255         totals)
0256                 do_totals_plotting
0257                 ;;
0258         slabs)
0259                 for i in "${files[@]}"; do
0260                         do_slabs_plotting "$i"
0261                 done
0262                 ;;
0263         *)
0264                 echo "Unknown mode $mode" >&2
0265                 usage
0266                 exit 1
0267         ;;
0268 esac