test_build_time.sh 6.4 KB

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