diff options
Diffstat (limited to 'bin/update_pch_autotune.sh')
-rwxr-xr-x | bin/update_pch_autotune.sh | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/bin/update_pch_autotune.sh b/bin/update_pch_autotune.sh new file mode 100755 index 000000000..ab9b0a688 --- /dev/null +++ b/bin/update_pch_autotune.sh @@ -0,0 +1,229 @@ +#! /bin/bash +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +# Finds the optimal update_pch settings that results in, +# per module and library, the fastest build time and +# smallest intermediate files (.o/.obj) output. + +# Usage: update_pch_autotune.sh [<module1> <module2>] +# Invoke: /opt/lo/bin/make cmd cmd="./bin/update_pch_autotune.sh [..]" + +# The resulting values may be entered in update_pch +# to be use for generating PCH in the future. +# Run this script after major header changes. + +root=`dirname $0` +root=`cd $root/.. && pwd` +cd $root + +if test -z "$1"; then + modules=`ls ./*/inc/pch/precompiled_*.hxx | sed -e s%./%% -e s%/.*%% | uniq` +else + modules="$@" +fi + +if [[ "$OSTYPE" == "cygwin" ]]; then + MAKE=/opt/lo/bin/make +else + MAKE=make +fi + +function build() +{ + local START=$(date +%s.%N) + + $MAKE -sr "$module" > /dev/null + status=$? + if [ $status -ne 0 ]; + then + # Spurious failures happen. + $MAKE "$module.build" > /dev/null + status=$? + fi + + local END=$(date +%s.%N1) + build_time=$(printf %.1f $(echo "$END - $START" | bc)) + + size="FAILED" + score="FAILED" + if [ $status -eq 0 ]; + then + # The total size of the object files. + size="$(du -s workdir/CxxObject/$module/ | awk '{print $1}')" + # Add the pch file size. + filename_rel="workdir/PrecompiledHeader/nodebug/$(basename $header)*" + filename_dbg="workdir/PrecompiledHeader/debug/$(basename $header)*" + if [[ $filename_rel -nt $filename_dbg ]]; then + pch_size="$(du -s $filename_rel | awk '{print $1}' | paste -sd+ | bc)" + else + pch_size="$(du -s $filename_dbg | awk '{print $1}' | paste -sd+ | bc)" + fi + size="$(echo "$pch_size + $size" | bc)" + + # Compute a score based on the build time and size. + # The shorter the build time, and smaller disk usage, the higher the score. + score=$(printf %.2f $(echo "10000 / ($build_time * e($size/1048576))" | bc -l)) + fi +} + +function run() +{ + local msg="$module.$libname, ${@:3}, " + printf "$msg" + ./bin/update_pch "$module" "$libname" "${@:3}" --silent + status=$? + + if [ $status -eq 0 ]; + then + build + + summary="$build_time, $size, $score" + if [ $status -eq 0 ]; + then + new_best_for_cuttof=$(echo "$score > $best_score_for_cuttof" | bc -l) + if [ $new_best_for_cuttof -eq 1 ]; + then + best_score_for_cuttof=$score + fi + + new_best=$(echo "$score > $best_score" | bc -l) + if [ $new_best -eq 1 ]; + then + best_score=$score + best_args="${@:3}" + best_time=$build_time + best_cutoff=$cutoff + summary="$build_time, $size, $score,*" + fi + fi + else + # Skip if pch is not updated. + summary="0, 0, 0" + fi + + echo "$summary" +} + +function args_to_table() +{ + local sys="EXCLUDE" + local mod="EXCLUDE" + local loc="EXCLUDE" + local cutoff=0 + IFS=' ' read -r -a aargs <<< $best_args + for index in "${!aargs[@]}" + do + if [ "${aargs[index]}" = "--include:system" ]; + then + sys="INCLUDE" + elif [ "${aargs[index]}" = "--exclude:system" ]; + then + sys="EXCLUDE" + elif [ "${aargs[index]}" = "--include:module" ]; + then + mod="INCLUDE" + elif [ "${aargs[index]}" = "--exclude:module" ]; + then + mod="EXCLUDE" + elif [ "${aargs[index]}" = "--include:local" ]; + then + loc="INCLUDE" + elif [ "${aargs[index]}" = "--exclude:local" ]; + then + loc="EXCLUDE" + elif [[ "${aargs[index]}" == *"cutoff"* ]] + then + cutoff=$(echo "${aargs[index]}" | grep -Po '\-\-cutoff\=\K\d+') + fi + done + + local key=$(printf "'%s.%s'" $module $libname) + echo "$(printf " %-36s: (%2d, %s, %s, %s), # %5.1f" $key $cutoff $sys $mod $loc $best_time)" +} + +for module in $modules; do + + # Build without pch includes as sanity check. + #run "$root" "$module" --cutoff=999 + + # Build before updating pch. + $MAKE "$module.build" > /dev/null + if [ $? -ne 0 ]; + then + # Build with dependencies before updating pch. + echo "Failed to build $module, building known state with dependencies..." + ./bin/update_pch.sh "$module" > /dev/null + $MAKE "$module.clean" > /dev/null + $MAKE "$module.all" > /dev/null + if [ $? -ne 0 ]; + then + # Build all! + echo "Failed to build $module with dependencies, building all..." + $MAKE build-nocheck > /dev/null + if [ $? -ne 0 ]; + then + >&2 echo "Broken build. Please revert changes and try again." + exit 1 + fi + fi + fi + + # Find pch files in the module to update. + headers=`find $root/$module/ -type f -iname "precompiled_*.hxx"` + + # Each pch belongs to a library. + for header in $headers; do + libname=`echo $header | sed -e s/.*precompiled_// -e s/\.hxx//` + #TODO: Backup the header and restore when last tune fails. + + # Force update on first try below. + echo "Autotuning $module.$libname..." + ./bin/update_pch "$module" "$libname" --cutoff=999 --silent --force + + best_score=0 + best_args="" + best_time=0 + best_cutoff=0 + for i in {1..16}; do + cutoff=$i + best_score_for_cuttof=0 + #run "$root" "$module" "--cutoff=$i" --include:system --exclude:module --exclude:local + run "$root" "$module" "--cutoff=$i" --exclude:system --exclude:module --exclude:local + #run "$root" "$module" "--cutoff=$i" --include:system --include:module --exclude:local + run "$root" "$module" "--cutoff=$i" --exclude:system --include:module --exclude:local + #run "$root" "$module" "--cutoff=$i" --include:system --exclude:module --include:local + run "$root" "$module" "--cutoff=$i" --exclude:system --exclude:module --include:local + #run "$root" "$module" "--cutoff=$i" --include:system --include:module --include:local + run "$root" "$module" "--cutoff=$i" --exclude:system --include:module --include:local + + if [ $i -gt $((best_cutoff+2)) ]; + then + score_too_low=$(echo "$best_score_for_cuttof < $best_score / 1.10" | bc -l) + if [ $score_too_low -eq 1 ]; + then + echo "Score hit low of $best_score_for_cuttof, well below overall best of $best_score. Stopping." + break; + fi + fi + done + + ./bin/update_pch "$module" "$libname" $best_args --force --silent + echo "> $module.$libname, $best_args, $best_time, $size, $score" + echo + + table+=$'\n' + table+="$(args_to_table)" + done + +done + +echo "Update the relevant lines in ./bin/update_pch script:" +>&2 echo "$table" + +exit 0 |