Tizen 2.0 Release
[framework/graphics/cairo.git] / perf / cairo-perf-diff
1 #!/bin/sh
2 set -e
3
4 usage() {
5     argv0=`basename $0`
6
7     cat >&2 << END
8 Usage:
9 For comparing files created my cairo-perf:
10
11         $argv0 old.perf new.perf
12
13 For comparing (cached) performance of revisions:
14
15         $argv0 [OPTIONS] <revision> [-- cairo-perf options]
16         $argv0 [OPTIONS] <rev1> <rev2> [-- cairo-perf-options]
17
18 If given a single revision, compares its results to that of its
19 (first-parent) predecessor. Otherwise compares the two given revisions.
20 The revisions can be any revision accepted by git. For example:
21
22         $argv0 HEAD             # Show impact of latest commit
23         $argv0 1.2.0 1.2.4      # Compare performance of 1.2.0 to 1.2.4
24
25 Options:
26
27 -f, --force
28         Forces cairo-perf-diff to re-run performance tests
29         even if cached performance data is available.
30
31 -h, --html
32         With this option performance changes are summarized
33         as HTML table.
34
35 -t, --trace
36         Compare performance using trace replays instead of
37         microbenchmarks.
38
39 Additional options can be passed the child cairo-perf process
40 by separating them with a double hyphen (--). For example, to
41 examine what the impact of the latest change is on the stroke
42 test you might use:
43
44         $argv0 HEAD -- stroke
45
46 The performance results are cached in .perf next to the .git directory.
47
48 Set CAIRO_AUTOGEN_OPTIONS to pass options to autogen for both
49 builds.
50 END
51
52     exit 1
53 }
54
55 benchmark="cairo-perf-micro"
56
57 # First, pull off any known options
58 while true; do
59     case $1 in
60         -f|--force) force_cairo_perf="true";;
61         -h|--html) html_output="$2"; shift ;;
62         -t|--trace) benchmark="cairo-perf-trace";;
63         *) break;;
64     esac
65
66     shift
67 done
68
69 # Then if anything is left that still looks like an option, (begins
70 # with a dash), give usage to catch --help or any other -garbage
71 if [ $# -eq 0 ] || [ "`echo "$1" | sed 's/^-//'`" != "$1" ]; then
72     usage
73 fi
74
75 # Finally, pick up the actual revision arguments
76 if [ $# -eq 1 ] || [ "$2" = "--" ]; then
77     old="$1^"
78     new="$1"
79     shift 1
80 else
81     old="$1"
82     new="$2"
83     shift 2
84 fi
85
86 # And post-finally, pass anything after -- on to cairo-perf
87 CAIRO_PERF_OPTIONS="-r -i 10"
88 if [ $# -gt 0 ]; then
89     if [ "$1" = "--" ]; then
90         shift 1
91         CAIRO_PERF_OPTIONS="$CAIRO_PERF_OPTIONS $@"
92     else
93         usage
94     fi
95 fi
96
97 git_setup() {
98     SUBDIRECTORY_OK='Yes'
99     . "$(git --exec-path)/git-sh-setup"
100     CAIRO_DIR=`dirname $GIT_DIR`
101     if [ "$CAIRO_DIR" = "." ]; then
102         CAIRO_DIR=`pwd`
103     fi
104     CAIRO_PERF_DIR=$CAIRO_DIR/.perf
105 }
106
107 rev2sha() {
108     rev=$1
109     git rev-parse --verify $rev || ( echo "Cannot resolve $rev as a git object" && exit 1 )
110 }
111
112 cpu_count() {
113     test -f /proc/cpuinfo &&
114     grep -c '^processor[[:blank:]]\+:' /proc/cpuinfo ||
115     echo 1
116 }
117
118 # We cache performance output based on a two-part name capturing the
119 # current performance test suite and the library being tested. We
120 # capture these as the tree object of the perf directory in HEAD and
121 # the tree object of the src directory of the revision being tested.
122 #
123 # This way, whenever the performance suite is updated, cached output
124 # from old versions of the suite are automatically invalidated. Also,
125 # if a commit just changes things outside of the src tree, (say it
126 # changes the "test" test suite, or README or configure.in, or
127 # whatever), cairo-perf-diff will be smart enough to still use cached
128 # results from a run with an equivalent src tree.
129 rev2perf() {
130     rev=$1
131     sha=`rev2sha $rev`
132     src_tree_sha=`rev2sha $rev:src`
133     perf_tree_sha=`rev2sha HEAD:perf`
134     script_tree_sha=`rev2sha HEAD:util/cairo-script`
135     echo "$CAIRO_PERF_DIR/${sha}-${perf_tree_sha}-${script_tree_sha}-${src_tree_sha}.perf"
136 }
137 rev2perf_glob() {
138     rev=$1
139     src_tree_sha=`rev2sha $rev:src`
140     perf_tree_sha=`rev2sha HEAD:perf`
141     script_tree_sha=`rev2sha HEAD:util/cairo-script`
142     echo "$CAIRO_PERF_DIR/*-${perf_tree_sha}-${script_tree_sha}-${src_tree_sha}.perf"
143 }
144
145 build() {
146     build_dir=$1
147     sha=$2
148
149     if [ ! -d $build_dir ]; then
150         git clone -s $CAIRO_DIR $build_dir
151         (cd $build_dir; git checkout -b tmp-cairo-perf-diff $sha)
152     fi
153     cd $build_dir
154
155     git checkout tmp-cairo-perf-diff
156     git reset --hard $sha
157
158     if [ -z "$MAKEFLAGS" ]; then
159         CPU_COUNT=`cpu_count`
160         export MAKEFLAGS="-j`expr $CPU_COUNT + 1`"
161     fi
162
163     if [ ! -e Makefile ]; then
164         ./autogen.sh $CAIRO_AUTOGEN_OPTIONS
165     fi
166
167     for file in $boilerplate_files; do
168         rsync $CAIRO_DIR/$file boilerplate
169     done
170     for file in $perf_files; do
171         rsync $CAIRO_DIR/$file perf
172     done
173     for file in $script_files; do
174         rsync $CAIRO_DIR/$file util/cairo-script
175     done
176
177     make || (rm config.cache && make)
178     (cd boilerplate && make libcairoboilerplate.la)
179
180     cd perf
181     make ${benchmark}
182 }
183
184 # Usage: run_cairo_perf_if_not_cached <rev> <suffix>
185 # The <rev> argument must be a valid git ref-spec that can
186 # be resolved to a commit. The suffix is just something
187 # unique so that build directories can be separated for
188 # multiple calls to this function.
189 run_cairo_perf_if_not_cached() {
190     rev=$1
191     build_dir="build-$2"
192
193     owd=`pwd`
194     sha=`rev2sha $rev`
195     perf=`rev2perf $rev`
196     glob=`rev2perf_glob $rev`
197     if [ -e $glob ] && [ "$force_cairo_perf" != "true" ]; then
198         return 0
199     fi
200     if [ ! -d $CAIRO_PERF_DIR ]; then
201         echo "Creating new perf cache in $CAIRO_PERF_DIR"
202         mkdir $CAIRO_PERF_DIR
203     fi
204
205     cd $CAIRO_DIR
206     boilerplate_files=`git ls-tree --name-only HEAD boilerplate/*`
207     perf_files=`git ls-tree --name-only HEAD perf/*`
208     script_files=`git ls-tree --name-only HEAD util/cairo-script/*`
209     cd $CAIRO_PERF_DIR
210
211     build $build_dir $sha || {
212         rm -rf $build_dir
213         build $build_dir $sha || exit 1
214     }
215
216     echo "Running \"cairo-perf $CAIRO_PERF_OPTIONS\" against $rev. Results will be cached in:"
217     { ./$benchmark $CAIRO_PERF_OPTIONS || echo "*** Performance test crashed"; } >> $perf
218
219     cd $owd
220 }
221
222 git_setup
223
224 if [ -e ./cairo-perf-diff-files ]; then
225         bindir="."
226 else
227         bindir=$CAIRO_DIR/perf
228
229         # Build cairo-perf-diff-files if not available
230         if [ ! -e $bindir/cairo-perf-diff-files ]; then
231             echo "Building cairo-perf-diff-files"
232             if [ "x$OS" = "xWindows_NT" ]; then
233                 make -f Makefile.win32 -C $bindir cairo-perf-diff-files CFG=debug
234             else
235                 make -C $bindir cairo-perf-diff-files
236             fi
237         fi
238 fi
239
240 if [ ! -e $old ]; then
241     run_cairo_perf_if_not_cached $old old
242     old=`rev2perf $old`
243 fi
244
245 if [ ! -e $new ]; then
246     run_cairo_perf_if_not_cached $new new
247     new=`rev2perf $new`
248 fi
249
250 if [ -z "$html_output" ]; then
251     $bindir/cairo-perf-diff-files $old $new
252 else
253     $bindir/cairo-perf-diff-files $old $new |
254     $CAIRO_DIR/perf/make-html.py > $html_output
255 fi