Linux 5.7.7
[linux/fpc-iii.git] / tools / vm / slabinfo-gnuplot.sh
blob26e193ffd2a2fd8b77042890cd94c40272dec7f5
1 #!/bin/bash
2 # SPDX-License-Identifier: GPL-2.0-only
4 # Sergey Senozhatsky, 2015
5 # sergey.senozhatsky.work@gmail.com
9 # This program is intended to plot a `slabinfo -X' stats, collected,
10 # for example, using the following command:
11 # while [ 1 ]; do slabinfo -X >> stats; sleep 1; done
13 # Use `slabinfo-gnuplot.sh stats' to pre-process collected records
14 # and generate graphs (totals, slabs sorted by size, slabs sorted
15 # by size).
17 # Graphs can be [individually] regenerate with different ranges and
18 # size (-r %d,%d and -s %d,%d options).
20 # To visually compare N `totals' graphs, do
21 # slabinfo-gnuplot.sh -t FILE1-totals FILE2-totals ... FILEN-totals
24 min_slab_name_size=11
25 xmin=0
26 xmax=0
27 width=1500
28 height=700
29 mode=preprocess
31 usage()
33 echo "Usage: [-s W,H] [-r MIN,MAX] [-t|-l] FILE1 [FILE2 ..]"
34 echo "FILEs must contain 'slabinfo -X' samples"
35 echo "-t - plot totals for FILE(s)"
36 echo "-l - plot slabs stats for FILE(s)"
37 echo "-s %d,%d - set image width and height"
38 echo "-r %d,%d - use data samples from a given range"
41 check_file_exist()
43 if [ ! -f "$1" ]; then
44 echo "File '$1' does not exist"
45 exit 1
49 do_slabs_plotting()
51 local file=$1
52 local out_file
53 local range="every ::$xmin"
54 local xtic=""
55 local xtic_rotate="norotate"
56 local lines=2000000
57 local wc_lines
59 check_file_exist "$file"
61 out_file=`basename "$file"`
62 if [ $xmax -ne 0 ]; then
63 range="$range::$xmax"
64 lines=$((xmax-xmin))
67 wc_lines=`cat "$file" | wc -l`
68 if [ $? -ne 0 ] || [ "$wc_lines" -eq 0 ] ; then
69 wc_lines=$lines
72 if [ "$wc_lines" -lt "$lines" ]; then
73 lines=$wc_lines
76 if [ $((width / lines)) -gt $min_slab_name_size ]; then
77 xtic=":xtic(1)"
78 xtic_rotate=90
81 gnuplot -p << EOF
82 #!/usr/bin/env gnuplot
84 set terminal png enhanced size $width,$height large
85 set output '$out_file.png'
86 set autoscale xy
87 set xlabel 'samples'
88 set ylabel 'bytes'
89 set style histogram columnstacked title textcolor lt -1
90 set style fill solid 0.15
91 set xtics rotate $xtic_rotate
92 set key left above Left title reverse
94 plot "$file" $range u 2$xtic title 'SIZE' with boxes,\
95 '' $range u 3 title 'LOSS' with boxes
96 EOF
98 if [ $? -eq 0 ]; then
99 echo "$out_file.png"
103 do_totals_plotting()
105 local gnuplot_cmd=""
106 local range="every ::$xmin"
107 local file=""
109 if [ $xmax -ne 0 ]; then
110 range="$range::$xmax"
113 for i in "${t_files[@]}"; do
114 check_file_exist "$i"
116 file="$file"`basename "$i"`
117 gnuplot_cmd="$gnuplot_cmd '$i' $range using 1 title\
118 '$i Memory usage' with lines,"
119 gnuplot_cmd="$gnuplot_cmd '' $range using 2 title \
120 '$i Loss' with lines,"
121 done
123 gnuplot -p << EOF
124 #!/usr/bin/env gnuplot
126 set terminal png enhanced size $width,$height large
127 set autoscale xy
128 set output '$file.png'
129 set xlabel 'samples'
130 set ylabel 'bytes'
131 set key left above Left title reverse
133 plot $gnuplot_cmd
136 if [ $? -eq 0 ]; then
137 echo "$file.png"
141 do_preprocess()
143 local out
144 local lines
145 local in=$1
147 check_file_exist "$in"
149 # use only 'TOP' slab (biggest memory usage or loss)
150 let lines=3
151 out=`basename "$in"`"-slabs-by-loss"
152 `cat "$in" | grep -A "$lines" 'Slabs sorted by loss' |\
153 egrep -iv '\-\-|Name|Slabs'\
154 | awk '{print $1" "$4+$2*$3" "$4}' > "$out"`
155 if [ $? -eq 0 ]; then
156 do_slabs_plotting "$out"
159 let lines=3
160 out=`basename "$in"`"-slabs-by-size"
161 `cat "$in" | grep -A "$lines" 'Slabs sorted by size' |\
162 egrep -iv '\-\-|Name|Slabs'\
163 | awk '{print $1" "$4" "$4-$2*$3}' > "$out"`
164 if [ $? -eq 0 ]; then
165 do_slabs_plotting "$out"
168 out=`basename "$in"`"-totals"
169 `cat "$in" | grep "Memory used" |\
170 awk '{print $3" "$7}' > "$out"`
171 if [ $? -eq 0 ]; then
172 t_files[0]=$out
173 do_totals_plotting
177 parse_opts()
179 local opt
181 while getopts "tlr::s::h" opt; do
182 case $opt in
184 mode=totals
187 mode=slabs
190 array=(${OPTARG//,/ })
191 width=${array[0]}
192 height=${array[1]}
195 array=(${OPTARG//,/ })
196 xmin=${array[0]}
197 xmax=${array[1]}
200 usage
201 exit 0
204 echo "Invalid option: -$OPTARG" >&2
205 exit 1
208 echo "-$OPTARG requires an argument." >&2
209 exit 1
211 esac
212 done
214 return $OPTIND
217 parse_args()
219 local idx=0
220 local p
222 for p in "$@"; do
223 case $mode in
224 preprocess)
225 files[$idx]=$p
226 idx=$idx+1
228 totals)
229 t_files[$idx]=$p
230 idx=$idx+1
232 slabs)
233 files[$idx]=$p
234 idx=$idx+1
236 esac
237 done
240 parse_opts "$@"
241 argstart=$?
242 parse_args "${@:$argstart}"
244 if [ ${#files[@]} -eq 0 ] && [ ${#t_files[@]} -eq 0 ]; then
245 usage
246 exit 1
249 case $mode in
250 preprocess)
251 for i in "${files[@]}"; do
252 do_preprocess "$i"
253 done
255 totals)
256 do_totals_plotting
258 slabs)
259 for i in "${files[@]}"; do
260 do_slabs_plotting "$i"
261 done
264 echo "Unknown mode $mode" >&2
265 usage
266 exit 1
268 esac