| #!/bin/bash |
| # Copyright 2020 The Fuchsia Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| # Script for measuring action tracing build overhead. |
| # See usage() below. |
| |
| set -Eeu |
| set -o pipefail |
| |
| # Constants: |
| |
| # These files will be locally modified for this experiment: |
| # Assume default output dir for now. |
| readonly args_gn=out/default/args.gn |
| readonly bcfg_gn=build/config/BUILDCONFIG.gn |
| |
| # The `time` binary has more options than the shell built-in. |
| time=/usr/bin/time |
| |
| # Where locally patched files and logs will be saved. |
| date="$(date +%Y.%m.%d.%H.%M.%S)" |
| readonly date |
| exp_dir="$(mktemp -t -d tmp.action_trace_overhead.$date.XXXX)" |
| readonly exp_dir |
| |
| function usage() { |
| cat <<EOF |
| $0 N |
| |
| This script measures the overhead of action-tracing. |
| Run this from \$FUCHSIA_DIR, your source checkout root. |
| |
| N: (positional) run the experiment this many times. |
| |
| This makes temporary changes to the following files, |
| but will restore them after all is done: |
| $args_gn |
| $bcfg_gn |
| |
| This leaves all others settings in args.gn, e.g. goma, untouched. |
| Temporary and log files will be kept in $exp_dir (example). |
| EOF |
| } |
| |
| # Expect one positional argument, print usage() otherwise. |
| test "$#" = 1 || { usage; exit 1;} |
| N="$1" |
| |
| # Disable tracing by patching the args.gn file. |
| function disable_trace() { |
| local _args_gn="$1" |
| if grep -q -w build_should_trace_actions "$_args_gn" |
| then |
| sed -e '/build_should_trace_actions/s|true|false|' "$_args_gn" |
| else |
| cat "$_args_gn" |
| echo "build_should_trace_actions = false" |
| fi |
| } |
| |
| # Enable tracing by patching the args.gn file. |
| function enable_trace() { |
| local _args_gn="$1" |
| if grep -q -w build_should_trace_actions "$_args_gn" |
| then |
| sed -e '/build_should_trace_actions/s|false|true|' "$_args_gn" |
| else |
| cat "$_args_gn" |
| echo "build_should_trace_actions = true" |
| fi |
| } |
| |
| function disable_checks() { |
| local _bcfg_gn="$1" |
| # Ignore trace errors, to let the build continue past trace errors. |
| # Force --no-check-access-permissions. |
| sed -e 's|--failed-check-status=1|--failed-check-status=0|' \ |
| -e '/if (!defined(hermetic_deps))/,/}/s|hermetic_deps = true|hermetic_deps = false|' \ |
| "$_bcfg_gn" |
| } |
| |
| function enable_checks() { |
| local _bcfg_gn="$1" |
| # Ignore trace errors, to let the build continue past trace errors. |
| # Let --check-access-permissions run by default, |
| # disregarding suppressions. |
| sed -e 's|--failed-check-status=1|--failed-check-status=0|' \ |
| -e '/if (!defined(hermetic_deps))/,/}/s|hermetic_deps = false|hermetic_deps = true|' \ |
| "$_bcfg_gn" |
| } |
| |
| # 1. Generate experiment configurations. |
| # Backup temporarily modified files |
| echo "Using temporary directory for local changes and logs: $exp_dir" |
| mkdir -p "$exp_dir"/"$(dirname "$args_gn")" |
| mkdir -p "$exp_dir"/"$(dirname "$bcfg_gn")" |
| cp "$args_gn" "$exp_dir"/"$args_gn".orig |
| cp "$bcfg_gn" "$exp_dir"/"$bcfg_gn".orig |
| |
| # Keep these around so we can diff them easily. |
| disable_trace "$exp_dir"/"$args_gn".orig > "$exp_dir"/"$args_gn.notrace" |
| enable_trace "$exp_dir"/"$args_gn".orig > "$exp_dir"/"$args_gn.trace" |
| |
| # Configure with checks enabled/disabled, ignoring suppressions. |
| disable_checks "$exp_dir"/"$bcfg_gn".orig > "$exp_dir"/"$bcfg_gn".nochecks |
| enable_checks "$exp_dir"/"$bcfg_gn".orig > "$exp_dir"/"$bcfg_gn".allchecks |
| |
| function vdiff() { |
| echo "diff -u $1 $2" |
| diff -u "$1" "$2" || : |
| } |
| |
| function vcat() { |
| echo "" |
| echo "<<< $1 <<<" |
| cat "$1" |
| echo ">>> $1 >>>" |
| } |
| |
| vdiff "$exp_dir"/"$args_gn".{orig,notrace} |
| vdiff "$exp_dir"/"$args_gn".{orig,trace} |
| vdiff "$exp_dir"/"$bcfg_gn".{orig,nochecks} |
| vdiff "$exp_dir"/"$bcfg_gn".{orig,allchecks} |
| |
| # Benchmark build one time. |
| function run_once() { |
| local log="$1" |
| # do `fx clean-build`, but only time the build part. |
| fx clean |
| # time the build and ignore any build errors |
| "$time" -a --output="$log" fx build || : |
| } |
| |
| ### Run benchmarks. |
| function run_all() { |
| local N="$1" |
| echo "=== Running all configurations ===" |
| |
| echo "===== Benchmarking baseline, with no tracing =====" |
| cp "$exp_dir"/"$args_gn".notrace "$args_gn" |
| cp "$exp_dir"/"$bcfg_gn".nochecks "$bcfg_gn" |
| fx gen |
| rm -f build.time.notrace |
| for i in $(seq $N); do |
| echo "======= run $i =======" |
| run_once "$exp_dir"/build.time.notrace |
| done |
| |
| echo "===== Benchmarking tracing, all checks disabled =====" |
| # 2. Measure with tracing, but no checks |
| cp "$exp_dir"/"$args_gn".trace "$args_gn" |
| cp "$exp_dir"/"$bcfg_gn".nochecks "$bcfg_gn" |
| fx gen |
| rm -f build.time.trace.nochecks |
| for i in $(seq $N); do |
| echo "======= run $i =======" |
| run_once "$exp_dir"/build.time.trace.nochecks |
| done |
| |
| echo "===== Benchmarking tracing, all checks enabled =====" |
| cp "$exp_dir"/"$args_gn".trace "$args_gn" |
| cp "$exp_dir"/"$bcfg_gn".allchecks "$bcfg_gn" |
| fx gen |
| rm -f build.time.trace.allchecks |
| for i in $(seq $N); do |
| echo "======= run $i =======" |
| run_once "$exp_dir"/build.time.trace.allchecks |
| done |
| |
| cat <<EOF |
| === All done. === |
| Files are in: $exp_dir |
| Test configurations are saved in: |
| |
| $exp_dir/$args_gn.notrace |
| $exp_dir/$args_gn.trace |
| |
| $exp_dir/$bcfg_gn.nochecks |
| $exp_dir/$bcfg_gn.allchecks |
| |
| Raw time logs are in: |
| $exp_dir/build.time.notrace (baseline, no tracing) |
| $exp_dir/build.time.trace.nochecks (traced, no checks) |
| $exp_dir/build.time.trace.allchecks (traced, all checks) |
| |
| EOF |
| echo "== Summary ==" |
| { |
| vcat $exp_dir/"$args_gn".orig |
| vcat $exp_dir/build.time.notrace |
| vcat $exp_dir/build.time.trace.nochecks |
| vcat $exp_dir/build.time.trace.allchecks |
| } | grep -v pagefaults | \ |
| sed -e '/CPU/s/\(user\|system\|elapsed\|\%CPU\)/ \1/g' \ |
| -e 's|CPU.*|CPU|' |
| } |
| |
| function restore_files() { |
| echo "=== Restoring original configuration. ===" |
| # Temporary files will still be left around for examination. |
| cp "$exp_dir/$args_gn".orig "$args_gn" |
| cp "$exp_dir/$bcfg_gn".orig "$bcfg_gn" |
| } |
| |
| trap restore_files EXIT |
| |
| run_all "$N" |
| |