build-perf-test.sh 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. #!/bin/bash
  2. #
  3. # This script runs a series of tests (with and without sstate) and reports build time (and tmp/ size)
  4. #
  5. # Build performance test script
  6. #
  7. # Copyright 2013 Intel Corporation
  8. #
  9. # This program is free software; you can redistribute it and/or modify
  10. # it under the terms of the GNU General Public License as published by
  11. # the Free Software Foundation; either version 2 of the License, or
  12. # (at your option) any later version.
  13. #
  14. # This program is distributed in the hope that it will be useful,
  15. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. # GNU General Public License for more details.
  18. #
  19. # You should have received a copy of the GNU General Public License
  20. # along with this program; if not, write to the Free Software
  21. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22. #
  23. #
  24. # AUTHORS:
  25. # Stefan Stanacar <stefanx.stanacar@intel.com>
  26. ME=$(basename $0)
  27. #
  28. # usage and setup
  29. #
  30. usage () {
  31. cat << EOT
  32. Usage: $ME [-h]
  33. $ME [-c <commit>] [-v] [-m <val>] [-j <val>] [-t <val>] [-i <image-name>] [-d <path>]
  34. Options:
  35. -h
  36. Display this help and exit.
  37. -c <commit>
  38. git checkout <commit> before anything else
  39. -v
  40. Show bitbake output, don't redirect it to a log.
  41. -m <machine>
  42. Value for MACHINE. Default is qemux86.
  43. -j <val>
  44. Value for PARALLEL_MAKE. Default is 8.
  45. -t <val>
  46. Value for BB_NUMBER_THREADS. Default is 8.
  47. -i <image-name>
  48. Instead of timing against core-image-sato, use <image-name>
  49. -d <path>
  50. Use <path> as DL_DIR
  51. -p <githash>
  52. Cherry pick githash onto the commit
  53. Note: current working directory must be inside a poky git clone.
  54. EOT
  55. }
  56. if clonedir=$(git rev-parse --show-toplevel); then
  57. cd $clonedir
  58. else
  59. echo "The current working dir doesn't seem to be a poky git clone. Please cd there before running $ME"
  60. exit 1
  61. fi
  62. IMAGE="core-image-sato"
  63. verbose=0
  64. dldir=
  65. commit=
  66. pmake=
  67. cherrypicks=
  68. while getopts "hvc:m:j:t:i:d:p:" opt; do
  69. case $opt in
  70. h) usage
  71. exit 0
  72. ;;
  73. v) verbose=1
  74. ;;
  75. c) commit=$OPTARG
  76. ;;
  77. m) export MACHINE=$OPTARG
  78. ;;
  79. j) pmake=$OPTARG
  80. ;;
  81. t) export BB_NUMBER_THREADS=$OPTARG
  82. ;;
  83. i) IMAGE=$OPTARG
  84. ;;
  85. d) dldir=$OPTARG
  86. ;;
  87. p) cherrypicks="$cherrypicks $OPTARG"
  88. ;;
  89. *) usage
  90. exit 1
  91. ;;
  92. esac
  93. done
  94. #drop cached credentials and test for sudo access without a password
  95. sudo -k -n ls > /dev/null 2>&1
  96. reqpass=$?
  97. if [ $reqpass -ne 0 ]; then
  98. echo "The script requires sudo access to drop caches between builds (echo 3 > /proc/sys/vm/drop_caches)"
  99. read -s -p "Please enter your sudo password: " pass
  100. echo
  101. fi
  102. if [ -n "$commit" ]; then
  103. echo "git checkout -f $commit"
  104. git pull > /dev/null 2>&1
  105. git checkout -f $commit || exit 1
  106. git pull > /dev/null 2>&1
  107. fi
  108. if [ -n "$cherrypicks" ]; then
  109. for c in $cherrypicks; do
  110. git cherry-pick $c
  111. done
  112. fi
  113. rev=$(git rev-parse --short HEAD) || exit 1
  114. OUTDIR="$clonedir/build-perf-test/results-$rev-`date "+%Y%m%d%H%M%S"`"
  115. BUILDDIR="$OUTDIR/build"
  116. resultsfile="$OUTDIR/results.log"
  117. cmdoutput="$OUTDIR/commands.log"
  118. myoutput="$OUTDIR/output.log"
  119. globalres="$clonedir/build-perf-test/globalres.log"
  120. mkdir -p $OUTDIR || exit 1
  121. log () {
  122. local msg="$1"
  123. echo "`date`: $msg" | tee -a $myoutput
  124. }
  125. #
  126. # Config stuff
  127. #
  128. branch=`git branch 2>&1 | grep "^* " | tr -d "* "`
  129. gitcommit=$(git rev-parse HEAD) || exit 1
  130. log "Running on $branch:$gitcommit"
  131. source ./oe-init-build-env $OUTDIR/build >/dev/null || exit 1
  132. cd $OUTDIR/build
  133. [ -n "$MACHINE" ] || export MACHINE="qemux86"
  134. [ -n "$BB_NUMBER_THREADS" ] || export BB_NUMBER_THREADS="8"
  135. if [ -n "$pmake" ]; then
  136. export PARALLEL_MAKE="-j $pmake"
  137. else
  138. export PARALLEL_MAKE="-j 8"
  139. fi
  140. if [ -n "$dldir" ]; then
  141. echo "DL_DIR = \"$dldir\"" >> conf/local.conf
  142. else
  143. echo "DL_DIR = \"$clonedir/build-perf-test/downloads\"" >> conf/local.conf
  144. fi
  145. # Sometimes I've noticed big differences in timings for the same commit, on the same machine
  146. # Disabling the network sanity check helps a bit (because of my crappy network connection and/or proxy)
  147. echo "CONNECTIVITY_CHECK_URIS =\"\"" >> conf/local.conf
  148. #
  149. # Functions
  150. #
  151. declare -a TIMES
  152. time_count=0
  153. declare -a SIZES
  154. size_count=0
  155. time_cmd () {
  156. log " Timing: $*"
  157. if [ $verbose -eq 0 ]; then
  158. /usr/bin/time -v -o $resultsfile "$@" >> $cmdoutput
  159. else
  160. /usr/bin/time -v -o $resultsfile "$@"
  161. fi
  162. ret=$?
  163. if [ $ret -eq 0 ]; then
  164. t=`grep wall $resultsfile | sed 's/.*m:ss): //'`
  165. log " TIME: $t"
  166. TIMES[(( time_count++ ))]="$t"
  167. else
  168. log "ERROR: exit status was non-zero, will report time as 0."
  169. TIMES[(( time_count++ ))]="0"
  170. fi
  171. #time by default overwrites the output file and we want to keep the results
  172. #it has an append option but I don't want to clobber the results in the same file
  173. i=`ls $OUTDIR/results.log* |wc -l`
  174. mv $resultsfile "${resultsfile}.${i}"
  175. log "More stats can be found in ${resultsfile}.${i}"
  176. }
  177. bbtime () {
  178. time_cmd bitbake "$@"
  179. }
  180. #we don't time bitbake here
  181. bbnotime () {
  182. local arg="$@"
  183. log " Running: bitbake ${arg}"
  184. if [ $verbose -eq 0 ]; then
  185. bitbake ${arg} >> $cmdoutput
  186. else
  187. bitbake ${arg}
  188. fi
  189. ret=$?
  190. if [ $ret -eq 0 ]; then
  191. log " Finished bitbake ${arg}"
  192. else
  193. log "ERROR: exit status was non-zero. Exit.."
  194. exit $ret
  195. fi
  196. }
  197. do_rmtmp() {
  198. log " Removing tmp"
  199. rm -rf bitbake.lock pseudodone conf/sanity_info cache tmp
  200. }
  201. do_rmsstate () {
  202. log " Removing sstate-cache"
  203. rm -rf sstate-cache
  204. }
  205. do_sync () {
  206. log " Syncing and dropping caches"
  207. sync; sync
  208. if [ $reqpass -eq 0 ]; then
  209. sudo sh -c "echo 3 > /proc/sys/vm/drop_caches"
  210. else
  211. echo "$pass" | sudo -S sh -c "echo 3 > /proc/sys/vm/drop_caches"
  212. echo
  213. fi
  214. sleep 3
  215. }
  216. write_results() {
  217. echo -n "`uname -n`,$branch:$gitcommit,`git describe`," >> $globalres
  218. for i in "${TIMES[@]}"; do
  219. echo -n "$i," >> $globalres
  220. done
  221. for i in "${SIZES[@]}"; do
  222. echo -n "$i," >> $globalres
  223. done
  224. echo >> $globalres
  225. sed -i '$ s/,$//' $globalres
  226. }
  227. ####
  228. #
  229. # Test 1
  230. # Measure: Wall clock of "bitbake core-image-sato" and size of tmp/dir (w/o rm_work and w/ rm_work)
  231. # Pre: Downloaded sources, no sstate
  232. # Steps:
  233. # Part1:
  234. # - fetchall
  235. # - clean build dir
  236. # - time bitbake core-image-sato
  237. # - collect data
  238. # Part2:
  239. # - bitbake virtual/kernel -c cleansstate
  240. # - time bitbake virtual/kernel
  241. # Part3:
  242. # - add INHERIT to local.conf
  243. # - clean build dir
  244. # - build
  245. # - report size, remove INHERIT
  246. test1_p1 () {
  247. log "Running Test 1, part 1/3: Measure wall clock of bitbake $IMAGE and size of tmp/ dir"
  248. bbnotime $IMAGE --runall=fetch
  249. do_rmtmp
  250. do_rmsstate
  251. do_sync
  252. bbtime $IMAGE
  253. s=`du -s tmp | sed 's/tmp//' | sed 's/[ \t]*$//'`
  254. SIZES[(( size_count++ ))]="$s"
  255. log "SIZE of tmp dir is: $s"
  256. log "Buildstats are saved in $OUTDIR/buildstats-test1"
  257. mv tmp/buildstats $OUTDIR/buildstats-test1
  258. }
  259. test1_p2 () {
  260. log "Running Test 1, part 2/3: bitbake virtual/kernel -c cleansstate and time bitbake virtual/kernel"
  261. bbnotime virtual/kernel -c cleansstate
  262. do_sync
  263. bbtime virtual/kernel
  264. }
  265. test1_p3 () {
  266. log "Running Test 1, part 3/3: Build $IMAGE w/o sstate and report size of tmp/dir with rm_work enabled"
  267. echo "INHERIT += \"rm_work\"" >> conf/local.conf
  268. do_rmtmp
  269. do_rmsstate
  270. do_sync
  271. bbtime $IMAGE
  272. sed -i 's/INHERIT += \"rm_work\"//' conf/local.conf
  273. s=`du -s tmp | sed 's/tmp//' | sed 's/[ \t]*$//'`
  274. SIZES[(( size_count++ ))]="$s"
  275. log "SIZE of tmp dir is: $s"
  276. log "Buildstats are saved in $OUTDIR/buildstats-test13"
  277. mv tmp/buildstats $OUTDIR/buildstats-test13
  278. }
  279. #
  280. # Test 2
  281. # Measure: Wall clock of "bitbake core-image-sato" and size of tmp/dir
  282. # Pre: populated sstate cache
  283. test2 () {
  284. # Assuming test 1 has run
  285. log "Running Test 2: Measure wall clock of bitbake $IMAGE -c rootfs with sstate"
  286. do_rmtmp
  287. do_sync
  288. bbtime $IMAGE -c rootfs
  289. }
  290. # Test 3
  291. # parsing time metrics
  292. #
  293. # Start with
  294. # i) "rm -rf tmp/cache; time bitbake -p"
  295. # ii) "rm -rf tmp/cache/default-glibc/; time bitbake -p"
  296. # iii) "time bitbake -p"
  297. test3 () {
  298. log "Running Test 3: Parsing time metrics (bitbake -p)"
  299. log " Removing tmp/cache && cache"
  300. rm -rf tmp/cache cache
  301. bbtime -p
  302. log " Removing tmp/cache/default-glibc/"
  303. rm -rf tmp/cache/default-glibc/
  304. bbtime -p
  305. bbtime -p
  306. }
  307. #
  308. # Test 4 - eSDK
  309. # Measure: eSDK size and installation time
  310. test4 () {
  311. log "Running Test 4: eSDK size and installation time"
  312. bbnotime $IMAGE -c do_populate_sdk_ext
  313. esdk_installer=(tmp/deploy/sdk/*-toolchain-ext-*.sh)
  314. if [ ${#esdk_installer[*]} -eq 1 ]; then
  315. s=$((`stat -c %s "$esdk_installer"` / 1024))
  316. SIZES[(( size_count++ ))]="$s"
  317. log "Download SIZE of eSDK is: $s kB"
  318. do_sync
  319. time_cmd "$esdk_installer" -y -d "tmp/esdk-deploy"
  320. s=$((`du -sb "tmp/esdk-deploy" | cut -f1` / 1024))
  321. SIZES[(( size_count++ ))]="$s"
  322. log "Install SIZE of eSDK is: $s kB"
  323. else
  324. log "ERROR: other than one sdk found (${esdk_installer[*]}), reporting size and time as 0."
  325. SIZES[(( size_count++ ))]="0"
  326. TIMES[(( time_count++ ))]="0"
  327. fi
  328. }
  329. # RUN!
  330. test1_p1
  331. test1_p2
  332. test1_p3
  333. test2
  334. test3
  335. test4
  336. # if we got til here write to global results
  337. write_results
  338. log "All done, cleaning up..."
  339. do_rmtmp
  340. do_rmsstate