test_build_time.sh 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. #!/bin/bash
  2. # Build performance regression test script
  3. #
  4. # Copyright 2011 Intel Corporation
  5. # All rights reserved.
  6. #
  7. # This program is free software; you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation; either version 2 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program; if not, write to the Free Software
  19. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. #
  21. #
  22. # DESCRIPTION
  23. # This script is intended to be used in conjunction with "git bisect run"
  24. # in order to find regressions in build time, however it can also be used
  25. # independently. It cleans out the build output directories, runs a
  26. # specified worker script (an example is test_build_time_worker.sh) under
  27. # TIME(1), logs the results to TEST_LOGDIR (default /tmp) and returns a
  28. # value telling "git bisect run" whether the build time is good (under
  29. # the specified threshold) or bad (over it). There is also a tolerance
  30. # option but it is not particularly useful as it only subtracts the
  31. # tolerance from the given threshold and uses it as the actual threshold.
  32. #
  33. # It is also capable of taking a file listing git revision hashes to be
  34. # test-applied to the repository in order to get past build failures that
  35. # would otherwise cause certain revisions to have to be skipped; if a
  36. # revision does not apply cleanly then the script assumes it does not
  37. # need to be applied and ignores it.
  38. #
  39. # Please see the help output (syntax below) for some important setup
  40. # instructions.
  41. #
  42. # AUTHORS
  43. # Paul Eggleton <paul.eggleton@linux.intel.com>
  44. syntax() {
  45. echo "syntax: $0 <script> <time> <tolerance> [patchrevlist]"
  46. echo ""
  47. echo " script - worker script file (if in current dir, prefix with ./)"
  48. echo " time - time threshold (in seconds, suffix m for minutes)"
  49. echo " tolerance - tolerance (in seconds, suffix m for minutes or % for"
  50. echo " percentage, can be 0)"
  51. echo " patchrevlist - optional file listing revisions to apply as patches on top"
  52. echo ""
  53. echo "You must set TEST_BUILDDIR to point to a previously created build directory,"
  54. echo "however please note that this script will wipe out the TMPDIR defined in"
  55. echo "TEST_BUILDDIR/conf/local.conf as part of its initial setup (as well as your"
  56. echo "~/.ccache)"
  57. echo ""
  58. echo "To get rid of the sudo prompt, please add the following line to /etc/sudoers"
  59. echo "(use 'visudo' to edit this; also it is assumed that the user you are running"
  60. echo "as is a member of the 'wheel' group):"
  61. echo ""
  62. echo "%wheel ALL=(ALL) NOPASSWD: /sbin/sysctl -w vm.drop_caches=[1-3]"
  63. echo ""
  64. echo "Note: it is recommended that you disable crond and any other process that"
  65. echo "may cause significant CPU or I/O usage during build performance tests."
  66. }
  67. # Note - we exit with 250 here because that will tell git bisect run that
  68. # something bad happened and stop
  69. if [ "$1" = "" ] ; then
  70. syntax
  71. exit 250
  72. fi
  73. if [ "$2" = "" ] ; then
  74. syntax
  75. exit 250
  76. fi
  77. if [ "$3" = "" ] ; then
  78. syntax
  79. exit 250
  80. fi
  81. if ! [[ "$2" =~ ^[0-9][0-9m.]*$ ]] ; then
  82. echo "'$2' is not a valid number for threshold"
  83. exit 250
  84. fi
  85. if ! [[ "$3" =~ ^[0-9][0-9m.%]*$ ]] ; then
  86. echo "'$3' is not a valid number for tolerance"
  87. exit 250
  88. fi
  89. if [ "$TEST_BUILDDIR" = "" ] ; then
  90. echo "Please set TEST_BUILDDIR to a previously created build directory"
  91. exit 250
  92. fi
  93. if [ ! -d "$TEST_BUILDDIR" ] ; then
  94. echo "TEST_BUILDDIR $TEST_BUILDDIR not found"
  95. exit 250
  96. fi
  97. git diff --quiet
  98. if [ $? != 0 ] ; then
  99. echo "Working tree is dirty, cannot proceed"
  100. exit 251
  101. fi
  102. if [ "$BB_ENV_EXTRAWHITE" != "" ] ; then
  103. echo "WARNING: you are running after sourcing the build environment script, this is not recommended"
  104. fi
  105. runscript=$1
  106. timethreshold=$2
  107. tolerance=$3
  108. if [ "$4" != "" ] ; then
  109. patchrevlist=`cat $4`
  110. else
  111. patchrevlist=""
  112. fi
  113. if [[ timethreshold == *m* ]] ; then
  114. timethreshold=`echo $timethreshold | sed s/m/*60/ | bc`
  115. fi
  116. if [[ $tolerance == *m* ]] ; then
  117. tolerance=`echo $tolerance | sed s/m/*60/ | bc`
  118. elif [[ $tolerance == *%* ]] ; then
  119. tolerance=`echo $tolerance | sed s/%//`
  120. tolerance=`echo "scale = 2; (($tolerance * $timethreshold) / 100)" | bc`
  121. fi
  122. tmpdir=`grep "^TMPDIR" $TEST_BUILDDIR/conf/local.conf | sed -e 's/TMPDIR[ \t]*=[ \t\?]*"//' -e 's/"//'`
  123. if [ "x$tmpdir" = "x" ]; then
  124. echo "Unable to determine TMPDIR from $TEST_BUILDDIR/conf/local.conf, bailing out"
  125. exit 250
  126. fi
  127. sstatedir=`grep "^SSTATE_DIR" $TEST_BUILDDIR/conf/local.conf | sed -e 's/SSTATE_DIR[ \t\?]*=[ \t]*"//' -e 's/"//'`
  128. if [ "x$sstatedir" = "x" ]; then
  129. echo "Unable to determine SSTATE_DIR from $TEST_BUILDDIR/conf/local.conf, bailing out"
  130. exit 250
  131. fi
  132. if [ `expr length $tmpdir` -lt 4 ] ; then
  133. echo "TMPDIR $tmpdir is less than 4 characters, bailing out"
  134. exit 250
  135. fi
  136. if [ `expr length $sstatedir` -lt 4 ] ; then
  137. echo "SSTATE_DIR $sstatedir is less than 4 characters, bailing out"
  138. exit 250
  139. fi
  140. echo -n "About to wipe out TMPDIR $tmpdir, press Ctrl+C to break out... "
  141. for i in 9 8 7 6 5 4 3 2 1
  142. do
  143. echo -ne "\x08$i"
  144. sleep 1
  145. done
  146. echo
  147. pushd . > /dev/null
  148. rm -f pseudodone
  149. echo "Removing TMPDIR $tmpdir..."
  150. rm -rf $tmpdir
  151. echo "Removing TMPDIR $tmpdir-*libc..."
  152. rm -rf $tmpdir-*libc
  153. echo "Removing SSTATE_DIR $sstatedir..."
  154. rm -rf $sstatedir
  155. echo "Removing ~/.ccache..."
  156. rm -rf ~/.ccache
  157. echo "Syncing..."
  158. sync
  159. sync
  160. echo "Dropping VM cache..."
  161. #echo 3 > /proc/sys/vm/drop_caches
  162. sudo /sbin/sysctl -w vm.drop_caches=3 > /dev/null
  163. if [ "$TEST_LOGDIR" = "" ] ; then
  164. logdir="/tmp"
  165. else
  166. logdir="$TEST_LOGDIR"
  167. fi
  168. rev=`git rev-parse HEAD`
  169. logfile="$logdir/timelog_$rev.log"
  170. echo -n > $logfile
  171. gitroot=`git rev-parse --show-toplevel`
  172. cd $gitroot
  173. for patchrev in $patchrevlist ; do
  174. echo "Applying $patchrev"
  175. patchfile=`mktemp`
  176. git show $patchrev > $patchfile
  177. git apply --check $patchfile &> /dev/null
  178. if [ $? != 0 ] ; then
  179. echo " ... patch does not apply without errors, ignoring"
  180. else
  181. echo "Applied $patchrev" >> $logfile
  182. git apply $patchfile &> /dev/null
  183. fi
  184. rm $patchfile
  185. done
  186. sync
  187. echo "Quiescing for 5s..."
  188. sleep 5
  189. echo "Running $runscript at $rev..."
  190. timeoutfile=`mktemp`
  191. /usr/bin/time -o $timeoutfile -f "%e\nreal\t%E\nuser\t%Us\nsys\t%Ss\nmaxm\t%Mk" $runscript 2>&1 | tee -a $logfile
  192. exitstatus=$PIPESTATUS
  193. git reset --hard HEAD > /dev/null
  194. popd > /dev/null
  195. timeresult=`head -n1 $timeoutfile`
  196. cat $timeoutfile | tee -a $logfile
  197. rm $timeoutfile
  198. if [ $exitstatus != 0 ] ; then
  199. # Build failed, exit with 125 to tell git bisect run to skip this rev
  200. echo "*** Build failed (exit code $exitstatus), skipping..." | tee -a $logfile
  201. exit 125
  202. fi
  203. ret=`echo "scale = 2; $timeresult > $timethreshold - $tolerance" | bc`
  204. echo "Returning $ret" | tee -a $logfile
  205. exit $ret