mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	Rename tools/vm to tools/mm for being more consistent with the code and documentation directories, and won't be confused with virtual machines. Link: https://lkml.kernel.org/r/20230103180754.129637-4-sj@kernel.org Signed-off-by: SeongJae Park <sj@kernel.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Shuah Khan <shuah@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.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' |\
 | 
						|
		grep -E -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' |\
 | 
						|
		grep -E -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
 |