blob: dcb388bd9f5ccff7d6a72c67f7d8a7dc97176dbc [file] [log] [blame]
#!/bin/bash
#
# Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
# Compares a series of compiler reivsions against a target application for
# statistic collection. Outputs a gnuplot consumable table.
APP=""
REV=""
ONE_DELTA=""
BASE_PATH=$(pwd)
SCRIPT_PATH=$(dirname $0)
SCRIPT_PATH=$(cd $SCRIPT_PATH; pwd)
RUNS=10
COUNT=50
LOW_REV=""
function printHelp() {
exitValue=${1:1}
echo "Compare performance of multiple compiler revisions against a given target application."
echo "Creates a cache of pre-built compiler revisions in compiler/revs/ for later comparison."
echo "The target output of this script is a gnuplot consumable list of stats (for now), located"
echo "in tmp_performance_comparisons/compiler_plots.dat."
echo ""
echo " Usage:"
echo " -a=, --app= The dart app file to test (required)."
echo " -d=, --one-delta= The filename, relative to app, to touch in order to trigger a one-delta compile."
echo " -r=, --revision= The compiler revision to start comparing against (default to current repository revision)."
echo " -c=, --count= The number of compiler revisions test against. Default 50."
echo " -l=, --low-rev= Alternative to --count; set the lowest revision to run to"
echo " -n=, --runs= How many times each compiler is run against the target application."
echo " -h, --help What you see is what you get."
exit $exitValue
}
function failTest() {
if [ ! $1 -eq 0 ]; then
echo $2
exit $1
fi
}
RESPONSE[0]="Performance: Better"
RESPONSE[1]="Performance: No Change"
RESPONSE[2]="Performance: Worse"
function calcStat() {
# Assume we're always making improvments, S2 will be presented as a larger value
LINEMATCH_DEV="s/${1}: .*stdev: \([0-9]*\).*/\1/p"
LINEMATCH_VALUE="s/${1}: average: \([0-9]*\).*/\1/p"
S1_DEV=$(sed -n -e "$LINEMATCH_DEV" $STAT1)
if [ "" != "$S1_DEV" ]; then
S1_VALUE=$(sed -n -e "$LINEMATCH_VALUE" $STAT1)
echo -ne "\t"$S1_VALUE"\t"$S1_DEV >> $PLOTS
else
echo -ne "\t-1\t-1" >> $PLOTS
fi
return 0
}
function calcStats() {
echo -n $1 >> $PLOTS
calcStat full-compile
calcStat zero-delta-compile
calcStat one-delta-compile
echo "" >> $PLOTS
}
if [ $# -eq 0 ]; then
printHelp;
fi
for i in $*
do
case $i in
--one-delta=*|-d=*)
ONE_DELTA=${i#*=}
COMPARE_OPTIONS+="--one-delta=$ONE_DELTA ";;
--app=*|-a=*)
APP=${i#*=};;
--revision=*|-r=*)
REV=${i#*=};;
--count=*|-c=*)
COUNT=${i#*=}
LOW_REV="";;
--runs=*|-n=*)
RUNS=${i#*=};;
--low-rev=*|-l=*)
LOW_REV=${i#*=}
COUNT=0;;
--help|-h)
printHelp 0;;
*)
echo "Parameter $i not recognized"
printHelp 1;;
esac
done
COMPARE_OPTIONS+="-r=$RUNS "
if ((RUNS > 0)); then
if [ "" = "$APP" ] || [ ! -r $APP ]; then
echo "Required --app" " got: $APP"
printHelp 1
fi
APP=$( cd "$( dirname "$APP" )" && pwd )/$( basename "$APP")
COMPARE_OPTIONS+="--app=$APP "
else
echo "Building up compiler cache"
APP="Compiler cache"
fi
ROOT_OF_REPO=$BASE_PATH
TEST_DIR=$BASE_PATH
while true; do
ls -d .gclient > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo "Root found: $ROOT_OF_REPO"
break;
fi
if [ "$TEST_DIR" = "/" ]; then
failTest 1 "Hit the root directory; no .git/ found?!"
fi
ROOT_OF_REPO=$TEST_DIR
cd ..
TEST_DIR=$(pwd)
done
# Make a temporary directory in the current path and checkout the revision
TMP_DIR=$ROOT_OF_REPO/compiler/tmp_performance_comparisons
mkdir -p $TMP_DIR
LOG_FILE=$TMP_DIR/compiler_compare.log
PLOTS=$TMP_DIR/compiler_plots.dat
STAT1=$TMP_DIR/compiler_metrics.txt
COMPARE_OPTIONS+="--output=$TMP_DIR "
# zero out files
echo "" > $LOG_FILE
# switch to tmp for remainder of building
cd $TMP_DIR
gclient config https://dart.googlecode.com/svn/branches/bleeding_edge/deps/compiler.deps >> $LOG_FILE 2>&1
failTest $? "Error calling gclient config"
if [ "" == "$REV" ]; then
echo "No revision specified; checking out head for test"
REV=`svn info https://dart.googlecode.com/svn/branches/bleeding_edge/deps/compiler.deps | sed -n -e 's/Revision: \([0-9]*\)/\1/p'`
echo "Head revision = $REV"
fi
function failStats() {
echo -e "$1\t-1\t0\t-1\t0\t-1\t0" >> $PLOTS
return 0;
}
function compileRevision() {
REVISION=$1
PREBUILT_DIR=$ROOT_OF_REPO/analyzer/revs/$REVISION/prebuilt
PREBUILT_BIN=$PREBUILT_DIR/analyzer/bin/dart_analyzer
if [ ! -x $PREBUILT_BIN ]; then
echo "No prebuilt, building and caching"
echo "Checking out clean version of $REVISION; will take some time. Look at $LOG_FILE for progress"
date
cd $TMP_DIR
gclient sync -t --revision=$REVISION >> $LOG_FILE 2>&1
failTest $? "Error calling gclient sync"
echo "Run hooks"
gclient runhooks >> $LOG_FILE 2>&1
echo "Compiling clean version of dart_analyzer"
date
cd compiler
../tools/build.py --mode release >> $LOG_FILE 2>&1
if [ ! $? -eq 0 ]; then
echo "error compiling"
failStats $REVISION
return 1;
fi
# Give the metrics system a backwards compatible way of getting to the
# artifacts that it needs.
cd ..
mkdir -p $ROOT_OF_REPO/compiler/revs/$REVISION/prebuilt
cd $ROOT_OF_REPO/compiler/revs/$REVISION/prebuilt
COMPILER_OUTDIR=$TMP_DIR/compiler/out/Release_ia32
cp -r $COMPILER_OUTDIR/compiler ./compiler
else
echo "Cached prebuilt of $REVISION!"
fi
# Short circuit if we're just filling in the build cache
if [ $RUNS -eq 0 ]; then
echo "run in compile only mode, no stats generating"
return 0;
fi
# Do the second test
echo "Running test with dart_analyzer $REVISION!"
date
echo $SCRIPT_PATH/analyzer_metrics.sh --stats-prefix=$REVISION --analyzer=$PREBUILT_DIR/analyzer/bin/dart_analyzer $COMPARE_OPTIONS >> $LOG_FILE 2>&1
$SCRIPT_PATH/analyzer_metrics.sh --stats-prefix=$REVISION --analyzer=$PREBUILT_DIR/analyzer/bin/dart_analyzer $COMPARE_OPTIONS > $STAT1
if [ ! $? -eq 0 ]; then
echo "error sampling"
failStats $REVISION
return 2;
fi
# Output the reivision to the PLOTS file; newline added after stats
calcStats $REVISION
}
echo -e "#Rev\tFull-ms\tdev\tZeroD\tdev\tOneD\tdev" > $PLOTS
if [ "$LOW_REV" ]; then
COUNT=$(( REV - LOW_REV + 1 ))
else
LOW_REV=$(( REV - COUNT + 1 ))
fi
for (( i = REV ; i >= LOW_REV ; i-- ))
do
echo "["$( basename "$APP")": "$((REV - i + 1))"/"$COUNT", rev:$i]"
compileRevision $i
done