Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.2.
  1#!/bin/bash
  2# SPDX-License-Identifier: GPL-2.0-only
  3
  4# Sergey Senozhatsky, 2015
  5# sergey.senozhatsky.work@gmail.com
  6#
  7
  8
  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
 12#
 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).
 16#
 17# Graphs can be [individually] regenerate with different ranges and
 18# size (-r %d,%d and -s %d,%d options).
 19#
 20# To visually compare N `totals' graphs, do
 21# slabinfo-gnuplot.sh -t FILE1-totals FILE2-totals ... FILEN-totals
 22#
 23
 24min_slab_name_size=11
 25xmin=0
 26xmax=0
 27width=1500
 28height=700
 29mode=preprocess
 30
 31usage()
 32{
 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"
 39}
 40
 41check_file_exist()
 42{
 43	if [ ! -f "$1" ]; then
 44		echo "File '$1' does not exist"
 45		exit 1
 46	fi
 47}
 48
 49do_slabs_plotting()
 50{
 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
 58
 59	check_file_exist "$file"
 60
 61	out_file=`basename "$file"`
 62	if [ $xmax -ne 0 ]; then
 63		range="$range::$xmax"
 64		lines=$((xmax-xmin))
 65	fi
 66
 67	wc_lines=`cat "$file" | wc -l`
 68	if [ $? -ne 0 ] || [ "$wc_lines" -eq 0 ] ; then
 69		wc_lines=$lines
 70	fi
 71
 72	if [ "$wc_lines" -lt "$lines" ]; then
 73		lines=$wc_lines
 74	fi
 75
 76	if [ $((width / lines)) -gt $min_slab_name_size ]; then
 77		xtic=":xtic(1)"
 78		xtic_rotate=90
 79	fi
 80
 81gnuplot -p << EOF
 82#!/usr/bin/env gnuplot
 83
 84set terminal png enhanced size $width,$height large
 85set output '$out_file.png'
 86set autoscale xy
 87set xlabel 'samples'
 88set ylabel 'bytes'
 89set style histogram columnstacked title textcolor lt -1
 90set style fill solid 0.15
 91set xtics rotate $xtic_rotate
 92set key left above Left title reverse
 93
 94plot "$file" $range u 2$xtic title 'SIZE' with boxes,\
 95	'' $range u 3 title 'LOSS' with boxes
 96EOF
 97
 98	if [ $? -eq 0 ]; then
 99		echo "$out_file.png"
100	fi
101}
102
103do_totals_plotting()
104{
105	local gnuplot_cmd=""
106	local range="every ::$xmin"
107	local file=""
108
109	if [ $xmax -ne 0 ]; then
110		range="$range::$xmax"
111	fi
112
113	for i in "${t_files[@]}"; do
114		check_file_exist "$i"
115
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
122
123gnuplot -p << EOF
124#!/usr/bin/env gnuplot
125
126set terminal png enhanced size $width,$height large
127set autoscale xy
128set output '$file.png'
129set xlabel 'samples'
130set ylabel 'bytes'
131set key left above Left title reverse
132
133plot $gnuplot_cmd
134EOF
135
136	if [ $? -eq 0 ]; then
137		echo "$file.png"
138	fi
139}
140
141do_preprocess()
142{
143	local out
144	local lines
145	local in=$1
146
147	check_file_exist "$in"
148
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		grep -E -iv '\-\-|Name|Slabs'\
154		| awk '{print $1" "$4+$2*$3" "$4}' > "$out"`
155	if [ $? -eq 0 ]; then
156		do_slabs_plotting "$out"
157	fi
158
159	let lines=3
160	out=`basename "$in"`"-slabs-by-size"
161	`cat "$in" | grep -A "$lines" 'Slabs sorted by size' |\
162		grep -E -iv '\-\-|Name|Slabs'\
163		| awk '{print $1" "$4" "$4-$2*$3}' > "$out"`
164	if [ $? -eq 0 ]; then
165		do_slabs_plotting "$out"
166	fi
167
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
174	fi
175}
176
177parse_opts()
178{
179	local opt
180
181	while getopts "tlr::s::h" opt; do
182		case $opt in
183			t)
184				mode=totals
185				;;
186			l)
187				mode=slabs
188				;;
189			s)
190				array=(${OPTARG//,/ })
191				width=${array[0]}
192				height=${array[1]}
193				;;
194			r)
195				array=(${OPTARG//,/ })
196				xmin=${array[0]}
197				xmax=${array[1]}
198				;;
199			h)
200				usage
201				exit 0
202				;;
203			\?)
204				echo "Invalid option: -$OPTARG" >&2
205				exit 1
206				;;
207			:)
208				echo "-$OPTARG requires an argument." >&2
209				exit 1
210				;;
211		esac
212	done
213
214	return $OPTIND
215}
216
217parse_args()
218{
219	local idx=0
220	local p
221
222	for p in "$@"; do
223		case $mode in
224			preprocess)
225				files[$idx]=$p
226				idx=$idx+1
227				;;
228			totals)
229				t_files[$idx]=$p
230				idx=$idx+1
231				;;
232			slabs)
233				files[$idx]=$p
234				idx=$idx+1
235				;;
236		esac
237	done
238}
239
240parse_opts "$@"
241argstart=$?
242parse_args "${@:$argstart}"
243
244if [ ${#files[@]} -eq 0 ] && [ ${#t_files[@]} -eq 0 ]; then
245	usage
246	exit 1
247fi
248
249case $mode in
250	preprocess)
251		for i in "${files[@]}"; do
252			do_preprocess "$i"
253		done
254		;;
255	totals)
256		do_totals_plotting
257		;;
258	slabs)
259		for i in "${files[@]}"; do
260			do_slabs_plotting "$i"
261		done
262		;;
263	*)
264		echo "Unknown mode $mode" >&2
265		usage
266		exit 1
267	;;
268esac