poky/scripts/contrib/build-perf-test.sh
Markus Lehtonen 7a52f67e59 build-perf-test.sh: add eSDK testing
Add simple initial eSDK test. Currently, only download size and
installation time of eSDK is measured. The eSDK to be tested is
generated from the same image that the other tests are run for. This
patch will add two new fields to the global results log and that needs
to be taken into account when examining the results.

(From OE-Core rev: c903c1e1f36a4dd1dc1b7a621fa7a6ffe7411119)

Signed-off-by: Markus Lehtonen <markus.lehtonen@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-01-25 12:44:13 +00:00

397 lines
10 KiB
Bash
Executable File

#!/bin/bash
#
# This script runs a series of tests (with and without sstate) and reports build time (and tmp/ size)
#
# Build performance test script
#
# Copyright 2013 Intel Corporation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#
# AUTHORS:
# Stefan Stanacar <stefanx.stanacar@intel.com>
ME=$(basename $0)
#
# usage and setup
#
usage () {
cat << EOT
Usage: $ME [-h]
$ME [-c <commit>] [-v] [-m <val>] [-j <val>] [-t <val>] [-i <image-name>] [-d <path>]
Options:
-h
Display this help and exit.
-c <commit>
git checkout <commit> before anything else
-v
Show bitbake output, don't redirect it to a log.
-m <machine>
Value for MACHINE. Default is qemux86.
-j <val>
Value for PARALLEL_MAKE. Default is 8.
-t <val>
Value for BB_NUMBER_THREADS. Default is 8.
-i <image-name>
Instead of timing against core-image-sato, use <image-name>
-d <path>
Use <path> as DL_DIR
-p <githash>
Cherry pick githash onto the commit
Note: current working directory must be inside a poky git clone.
EOT
}
if clonedir=$(git rev-parse --show-toplevel); then
cd $clonedir
else
echo "The current working dir doesn't seem to be a poky git clone. Please cd there before running $ME"
exit 1
fi
IMAGE="core-image-sato"
verbose=0
dldir=
commit=
pmake=
cherrypicks=
while getopts "hvc:m:j:t:i:d:p:" opt; do
case $opt in
h) usage
exit 0
;;
v) verbose=1
;;
c) commit=$OPTARG
;;
m) export MACHINE=$OPTARG
;;
j) pmake=$OPTARG
;;
t) export BB_NUMBER_THREADS=$OPTARG
;;
i) IMAGE=$OPTARG
;;
d) dldir=$OPTARG
;;
p) cherrypicks="$cherrypicks $OPTARG"
;;
*) usage
exit 1
;;
esac
done
#drop cached credentials and test for sudo access without a password
sudo -k -n ls > /dev/null 2>&1
reqpass=$?
if [ $reqpass -ne 0 ]; then
echo "The script requires sudo access to drop caches between builds (echo 3 > /proc/sys/vm/drop_caches)"
read -s -p "Please enter your sudo password: " pass
echo
fi
if [ -n "$commit" ]; then
echo "git checkout -f $commit"
git pull > /dev/null 2>&1
git checkout -f $commit || exit 1
git pull > /dev/null 2>&1
fi
if [ -n "$cherrypicks" ]; then
for c in $cherrypicks; do
git cherry-pick $c
done
fi
rev=$(git rev-parse --short HEAD) || exit 1
OUTDIR="$clonedir/build-perf-test/results-$rev-`date "+%Y%m%d%H%M%S"`"
BUILDDIR="$OUTDIR/build"
resultsfile="$OUTDIR/results.log"
cmdoutput="$OUTDIR/commands.log"
myoutput="$OUTDIR/output.log"
globalres="$clonedir/build-perf-test/globalres.log"
mkdir -p $OUTDIR || exit 1
log () {
local msg="$1"
echo "`date`: $msg" | tee -a $myoutput
}
#
# Config stuff
#
branch=`git branch 2>&1 | grep "^* " | tr -d "* "`
gitcommit=$(git rev-parse HEAD) || exit 1
log "Running on $branch:$gitcommit"
source ./oe-init-build-env $OUTDIR/build >/dev/null || exit 1
cd $OUTDIR/build
[ -n "$MACHINE" ] || export MACHINE="qemux86"
[ -n "$BB_NUMBER_THREADS" ] || export BB_NUMBER_THREADS="8"
if [ -n "$pmake" ]; then
export PARALLEL_MAKE="-j $pmake"
else
export PARALLEL_MAKE="-j 8"
fi
if [ -n "$dldir" ]; then
echo "DL_DIR = \"$dldir\"" >> conf/local.conf
else
echo "DL_DIR = \"$clonedir/build-perf-test/downloads\"" >> conf/local.conf
fi
# Sometimes I've noticed big differences in timings for the same commit, on the same machine
# Disabling the network sanity check helps a bit (because of my crappy network connection and/or proxy)
echo "CONNECTIVITY_CHECK_URIS =\"\"" >> conf/local.conf
#
# Functions
#
declare -a TIMES
time_count=0
declare -a SIZES
size_count=0
time_cmd () {
log " Timing: $*"
if [ $verbose -eq 0 ]; then
/usr/bin/time -v -o $resultsfile "$@" >> $cmdoutput
else
/usr/bin/time -v -o $resultsfile "$@"
fi
ret=$?
if [ $ret -eq 0 ]; then
t=`grep wall $resultsfile | sed 's/.*m:ss): //'`
log " TIME: $t"
TIMES[(( time_count++ ))]="$t"
else
log "ERROR: exit status was non-zero, will report time as 0."
TIMES[(( time_count++ ))]="0"
fi
#time by default overwrites the output file and we want to keep the results
#it has an append option but I don't want to clobber the results in the same file
i=`ls $OUTDIR/results.log* |wc -l`
mv $resultsfile "${resultsfile}.${i}"
log "More stats can be found in ${resultsfile}.${i}"
}
bbtime () {
time_cmd bitbake "$@"
}
#we don't time bitbake here
bbnotime () {
local arg="$@"
log " Running: bitbake ${arg}"
if [ $verbose -eq 0 ]; then
bitbake ${arg} >> $cmdoutput
else
bitbake ${arg}
fi
ret=$?
if [ $ret -eq 0 ]; then
log " Finished bitbake ${arg}"
else
log "ERROR: exit status was non-zero. Exit.."
exit $ret
fi
}
do_rmtmp() {
log " Removing tmp"
rm -rf bitbake.lock pseudodone conf/sanity_info cache tmp
}
do_rmsstate () {
log " Removing sstate-cache"
rm -rf sstate-cache
}
do_sync () {
log " Syncing and dropping caches"
sync; sync
if [ $reqpass -eq 0 ]; then
sudo sh -c "echo 3 > /proc/sys/vm/drop_caches"
else
echo "$pass" | sudo -S sh -c "echo 3 > /proc/sys/vm/drop_caches"
echo
fi
sleep 3
}
write_results() {
echo -n "`uname -n`,$branch:$gitcommit,`git describe`," >> $globalres
for i in "${TIMES[@]}"; do
echo -n "$i," >> $globalres
done
for i in "${SIZES[@]}"; do
echo -n "$i," >> $globalres
done
echo >> $globalres
sed -i '$ s/,$//' $globalres
}
####
#
# Test 1
# Measure: Wall clock of "bitbake core-image-sato" and size of tmp/dir (w/o rm_work and w/ rm_work)
# Pre: Downloaded sources, no sstate
# Steps:
# Part1:
# - fetchall
# - clean build dir
# - time bitbake core-image-sato
# - collect data
# Part2:
# - bitbake virtual/kernel -c cleansstate
# - time bitbake virtual/kernel
# Part3:
# - add INHERIT to local.conf
# - clean build dir
# - build
# - report size, remove INHERIT
test1_p1 () {
log "Running Test 1, part 1/3: Measure wall clock of bitbake $IMAGE and size of tmp/ dir"
bbnotime $IMAGE -c fetchall
do_rmtmp
do_rmsstate
do_sync
bbtime $IMAGE
s=`du -s tmp | sed 's/tmp//' | sed 's/[ \t]*$//'`
SIZES[(( size_count++ ))]="$s"
log "SIZE of tmp dir is: $s"
log "Buildstats are saved in $OUTDIR/buildstats-test1"
mv tmp/buildstats $OUTDIR/buildstats-test1
}
test1_p2 () {
log "Running Test 1, part 2/3: bitbake virtual/kernel -c cleansstate and time bitbake virtual/kernel"
bbnotime virtual/kernel -c cleansstate
do_sync
bbtime virtual/kernel
}
test1_p3 () {
log "Running Test 1, part 3/3: Build $IMAGE w/o sstate and report size of tmp/dir with rm_work enabled"
echo "INHERIT += \"rm_work\"" >> conf/local.conf
do_rmtmp
do_rmsstate
do_sync
bbtime $IMAGE
sed -i 's/INHERIT += \"rm_work\"//' conf/local.conf
s=`du -s tmp | sed 's/tmp//' | sed 's/[ \t]*$//'`
SIZES[(( size_count++ ))]="$s"
log "SIZE of tmp dir is: $s"
log "Buildstats are saved in $OUTDIR/buildstats-test13"
mv tmp/buildstats $OUTDIR/buildstats-test13
}
#
# Test 2
# Measure: Wall clock of "bitbake core-image-sato" and size of tmp/dir
# Pre: populated sstate cache
test2 () {
# Assuming test 1 has run
log "Running Test 2: Measure wall clock of bitbake $IMAGE -c rootfs with sstate"
do_rmtmp
do_sync
bbtime $IMAGE -c rootfs
}
# Test 3
# parsing time metrics
#
# Start with
# i) "rm -rf tmp/cache; time bitbake -p"
# ii) "rm -rf tmp/cache/default-glibc/; time bitbake -p"
# iii) "time bitbake -p"
test3 () {
log "Running Test 3: Parsing time metrics (bitbake -p)"
log " Removing tmp/cache && cache"
rm -rf tmp/cache cache
bbtime -p
log " Removing tmp/cache/default-glibc/"
rm -rf tmp/cache/default-glibc/
bbtime -p
bbtime -p
}
#
# Test 4 - eSDK
# Measure: eSDK size and installation time
test4 () {
log "Running Test 4: eSDK size and installation time"
bbnotime $IMAGE -c do_populate_sdk_ext
esdk_installer=(tmp/deploy/sdk/*-toolchain-ext-*.sh)
if [ ${#esdk_installer[*]} -eq 1 ]; then
s=$((`stat -c %s "$esdk_installer"` / 1024))
SIZES[(( size_count++ ))]="$s"
log "Download SIZE of eSDK is: $s kB"
do_sync
time_cmd "$esdk_installer" -y -d "tmp/esdk-deploy"
else
log "ERROR: other than one sdk found (${esdk_installer[*]}), reporting size and time as 0."
SIZES[(( size_count++ ))]="0"
TIMES[(( time_count++ ))]="0"
fi
}
# RUN!
test1_p1
test1_p2
test1_p3
test2
test3
test4
# if we got til here write to global results
write_results
log "All done, cleaning up..."
do_rmtmp
do_rmsstate