xref: /OK3568_Linux_fs/yocto/poky/scripts/contrib/bb-perf/buildstats-plot.sh (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#!/usr/bin/env bash
2*4882a593Smuzhiyun#
3*4882a593Smuzhiyun# Copyright (c) 2011, Intel Corporation.
4*4882a593Smuzhiyun#
5*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-or-later
6*4882a593Smuzhiyun#
7*4882a593Smuzhiyun# DESCRIPTION
8*4882a593Smuzhiyun#
9*4882a593Smuzhiyun# Produces script data to be consumed by gnuplot. There are two possible plots
10*4882a593Smuzhiyun# depending if either the -S parameter is present or not:
11*4882a593Smuzhiyun#
12*4882a593Smuzhiyun#     * without -S: Produces a histogram listing top N recipes/tasks versus
13*4882a593Smuzhiyun#       stats. The first stat defined in the -s parameter is the one taken
14*4882a593Smuzhiyun#       into account for ranking
15*4882a593Smuzhiyun#     * -S: Produces a histogram listing tasks versus stats.  In this case,
16*4882a593Smuzhiyun#       the value of each stat is the sum for that particular stat in all recipes found.
17*4882a593Smuzhiyun#       Stats values  are in descending order defined by the first stat defined on -s
18*4882a593Smuzhiyun#
19*4882a593Smuzhiyun# EXAMPLES
20*4882a593Smuzhiyun#
21*4882a593Smuzhiyun# 1. Top recipes' tasks taking into account utime
22*4882a593Smuzhiyun#
23*4882a593Smuzhiyun#     $ buildstats-plot.sh -s utime | gnuplot -p
24*4882a593Smuzhiyun#
25*4882a593Smuzhiyun# 2. Tasks versus utime:stime
26*4882a593Smuzhiyun#
27*4882a593Smuzhiyun#     $ buildstats-plot.sh -s utime:stime -S | gnuplot -p
28*4882a593Smuzhiyun#
29*4882a593Smuzhiyun# 3. Tasks versus IO write_bytes:IO read_bytes
30*4882a593Smuzhiyun#
31*4882a593Smuzhiyun#     $ buildstats-plot.sh -s 'IO write_bytes:IO read_bytes' -S | gnuplot -p
32*4882a593Smuzhiyun#
33*4882a593Smuzhiyun# AUTHORS
34*4882a593Smuzhiyun# Leonardo Sandoval <leonardo.sandoval.gonzalez@linux.intel.com>
35*4882a593Smuzhiyun#
36*4882a593Smuzhiyun
37*4882a593Smuzhiyunset -o nounset
38*4882a593Smuzhiyunset -o errexit
39*4882a593Smuzhiyun
40*4882a593SmuzhiyunBS_DIR="tmp/buildstats"
41*4882a593SmuzhiyunN=10
42*4882a593SmuzhiyunRECIPE=""
43*4882a593SmuzhiyunTASKS="compile:configure:fetch:install:patch:populate_lic:populate_sysroot:unpack"
44*4882a593SmuzhiyunSTATS="utime"
45*4882a593SmuzhiyunACCUMULATE=""
46*4882a593SmuzhiyunSUM=""
47*4882a593SmuzhiyunOUTDATA_FILE="$PWD/buildstats-plot.out"
48*4882a593Smuzhiyun
49*4882a593Smuzhiyunfunction usage {
50*4882a593Smuzhiyun    CMD=$(basename $0)
51*4882a593Smuzhiyun    cat <<EOM
52*4882a593SmuzhiyunUsage: $CMD [-b buildstats_dir] [-t do_task]
53*4882a593Smuzhiyun  -b buildstats The path where the folder resides
54*4882a593Smuzhiyun                (default: "$BS_DIR")
55*4882a593Smuzhiyun  -n N          Top N recipes to display. Ignored if -S is present
56*4882a593Smuzhiyun                (default: "$N")
57*4882a593Smuzhiyun  -r recipe     The recipe mask to be searched
58*4882a593Smuzhiyun  -t tasks      The tasks to be computed
59*4882a593Smuzhiyun                (default: "$TASKS")
60*4882a593Smuzhiyun  -s stats      The stats to be matched. If more that one stat, units
61*4882a593Smuzhiyun                should be the same because data is plot as histogram.
62*4882a593Smuzhiyun                (see buildstats.sh -h for all options) or any other defined
63*4882a593Smuzhiyun                (build)stat separated by colons, i.e. stime:utime
64*4882a593Smuzhiyun                (default: "$STATS")
65*4882a593Smuzhiyun  -a            Accumulate all stats values for found recipes
66*4882a593Smuzhiyun  -S            Sum values for a particular stat for found recipes
67*4882a593Smuzhiyun  -o            Output data file.
68*4882a593Smuzhiyun                (default: "$OUTDATA_FILE")
69*4882a593Smuzhiyun  -h            Display this help message
70*4882a593SmuzhiyunEOM
71*4882a593Smuzhiyun}
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun# Parse and validate arguments
74*4882a593Smuzhiyunwhile getopts "b:n:r:t:s:o:aSh" OPT; do
75*4882a593Smuzhiyun    case $OPT in
76*4882a593Smuzhiyun    b)
77*4882a593Smuzhiyun        BS_DIR="$OPTARG"
78*4882a593Smuzhiyun        ;;
79*4882a593Smuzhiyun    n)
80*4882a593Smuzhiyun        N="$OPTARG"
81*4882a593Smuzhiyun        ;;
82*4882a593Smuzhiyun    r)
83*4882a593Smuzhiyun        RECIPE="-r $OPTARG"
84*4882a593Smuzhiyun        ;;
85*4882a593Smuzhiyun    t)
86*4882a593Smuzhiyun        TASKS="$OPTARG"
87*4882a593Smuzhiyun        ;;
88*4882a593Smuzhiyun    s)
89*4882a593Smuzhiyun        STATS="$OPTARG"
90*4882a593Smuzhiyun        ;;
91*4882a593Smuzhiyun    a)
92*4882a593Smuzhiyun        ACCUMULATE="-a"
93*4882a593Smuzhiyun        ;;
94*4882a593Smuzhiyun    S)
95*4882a593Smuzhiyun        SUM="y"
96*4882a593Smuzhiyun        ;;
97*4882a593Smuzhiyun    o)
98*4882a593Smuzhiyun        OUTDATA_FILE="$OPTARG"
99*4882a593Smuzhiyun        ;;
100*4882a593Smuzhiyun    h)
101*4882a593Smuzhiyun        usage
102*4882a593Smuzhiyun        exit 0
103*4882a593Smuzhiyun        ;;
104*4882a593Smuzhiyun    *)
105*4882a593Smuzhiyun        usage
106*4882a593Smuzhiyun        exit 1
107*4882a593Smuzhiyun        ;;
108*4882a593Smuzhiyun    esac
109*4882a593Smuzhiyundone
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun# Get number of stats
112*4882a593SmuzhiyunIFS=':'; statsarray=(${STATS}); unset IFS
113*4882a593Smuzhiyunnstats=${#statsarray[@]}
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun# Get script folder, use to run buildstats.sh
116*4882a593SmuzhiyunCD=$(dirname $0)
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun# Parse buildstats recipes to produce a single table
119*4882a593SmuzhiyunOUTBUILDSTATS="$PWD/buildstats.log"
120*4882a593Smuzhiyun$CD/buildstats.sh -b "$BS_DIR" -s "$STATS" -t "$TASKS" $RECIPE $ACCUMULATE -H > $OUTBUILDSTATS
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun# Get headers
123*4882a593SmuzhiyunHEADERS=$(cat $OUTBUILDSTATS | sed -n -e 's/\(.*\)/"\1"/' -e '1s/ /\\\\\\\\ /g' -e 's/_/\\\\\\\\_/g' -e '1s/:/" "/gp')
124*4882a593Smuzhiyun
125*4882a593Smuzhiyunecho -e "set boxwidth 0.9 relative"
126*4882a593Smuzhiyunecho -e "set style data histograms"
127*4882a593Smuzhiyunecho -e "set style fill solid 1.0 border lt -1"
128*4882a593Smuzhiyunecho -e "set xtics rotate by 45 right"
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun# Get output data
131*4882a593Smuzhiyunif [ -z "$SUM" ]; then
132*4882a593Smuzhiyun    cat $OUTBUILDSTATS | sed -e '1d' -e 's/_/\\\\_/g' | sort -k3 -n -r | head -$N > $OUTDATA_FILE
133*4882a593Smuzhiyun    # include task at recipe column
134*4882a593Smuzhiyun    sed -i -e "1i\
135*4882a593Smuzhiyun${HEADERS}" $OUTDATA_FILE
136*4882a593Smuzhiyun    echo -e "set title \"Top task/recipes\""
137*4882a593Smuzhiyun    echo -e "plot for [COL=3:`expr 3 + ${nstats} - 1`] '${OUTDATA_FILE}' using COL:xtic(stringcolumn(1).' '.stringcolumn(2)) title columnheader(COL)"
138*4882a593Smuzhiyunelse
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun    # Construct datatamash sum argument (sum 3 sum 4 ...)
141*4882a593Smuzhiyun    declare -a sumargs
142*4882a593Smuzhiyun    j=0
143*4882a593Smuzhiyun    for i in `seq $nstats`; do
144*4882a593Smuzhiyun        sumargs[j]=sum; j=$(( $j + 1 ))
145*4882a593Smuzhiyun        sumargs[j]=`expr 3 + $i - 1`;  j=$(( $j + 1 ))
146*4882a593Smuzhiyun    done
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun    # Do the processing with datamash
149*4882a593Smuzhiyun    cat $OUTBUILDSTATS | sed -e '1d' | datamash -t ' ' -g1 ${sumargs[*]} | sort -k2 -n -r > $OUTDATA_FILE
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun    # Include headers into resulted file, so we can include gnuplot xtics
152*4882a593Smuzhiyun    HEADERS=$(echo $HEADERS | sed -e 's/recipe//1')
153*4882a593Smuzhiyun    sed -i -e "1i\
154*4882a593Smuzhiyun${HEADERS}" $OUTDATA_FILE
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun    # Plot
157*4882a593Smuzhiyun    echo -e "set title \"Sum stats values per task for all recipes\""
158*4882a593Smuzhiyun    echo -e "plot for [COL=2:`expr 2 + ${nstats} - 1`] '${OUTDATA_FILE}' using COL:xtic(1) title columnheader(COL)"
159*4882a593Smuzhiyunfi
160*4882a593Smuzhiyun
161