Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/mm/slabinfo-gnuplot.sh
26285 views
1
#!/bin/bash
2
# SPDX-License-Identifier: GPL-2.0-only
3
4
# Sergey Senozhatsky, 2015
5
# [email protected]
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
24
min_slab_name_size=11
25
xmin=0
26
xmax=0
27
width=1500
28
height=700
29
mode=preprocess
30
31
usage()
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
41
check_file_exist()
42
{
43
if [ ! -f "$1" ]; then
44
echo "File '$1' does not exist"
45
exit 1
46
fi
47
}
48
49
do_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
81
gnuplot -p << EOF
82
#!/usr/bin/env gnuplot
83
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
93
94
plot "$file" $range u 2$xtic title 'SIZE' with boxes,\
95
'' $range u 3 title 'LOSS' with boxes
96
EOF
97
98
if [ $? -eq 0 ]; then
99
echo "$out_file.png"
100
fi
101
}
102
103
do_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
123
gnuplot -p << EOF
124
#!/usr/bin/env gnuplot
125
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
132
133
plot $gnuplot_cmd
134
EOF
135
136
if [ $? -eq 0 ]; then
137
echo "$file.png"
138
fi
139
}
140
141
do_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
177
parse_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
217
parse_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
240
parse_opts "$@"
241
argstart=$?
242
parse_args "${@:$argstart}"
243
244
if [ ${#files[@]} -eq 0 ] && [ ${#t_files[@]} -eq 0 ]; then
245
usage
246
exit 1
247
fi
248
249
case $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
;;
268
esac
269
270