123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400 |
- #!/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 --runall=fetch
- 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"
- s=$((`du -sb "tmp/esdk-deploy" | cut -f1` / 1024))
- SIZES[(( size_count++ ))]="$s"
- log "Install SIZE of eSDK is: $s kB"
- 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
|