#!/bin/bash set -euf -o pipefail scripts=$(dirname $0) # shellcheck source=jenkins-helpers.sh . $scripts/jenkins-helpers.sh # shellcheck source=round-robin.sh . $scripts/round-robin.sh convert_args_to_variables "$@" obligatory_variables rr[ci_project] rr[ci_config] declare -A rr # All bmk config about hw and benchs is implemented in this file # shellcheck source=tcwg_bmk-config.sh . $scripts/tcwg_bmk-config.sh # Execution mode: build or bisect rr[mode]="${rr[mode]-build}" # Set custom revision for one of the projects, and use baseline revisions # for all other projects. rr[baseline_branch]="${rr[baseline_branch]-linaro-local/ci/${rr[ci_project]}/${rr[ci_config]}}" rr[update_baseline]="${rr[update_baseline]-ignore}" rr[top_artifacts]="${rr[top_artifacts]-$(pwd)/artifacts}" # ${ci_project}--${ci_config} format is : # 'tcwg_bmk-#{PROFILE_NAME}-#{BMK}--#{TOOLCHAIN}-#{TARGET}-{toolchain_ver}-{cflags}' IFS=- read -a ci_pjt_cfg < $run_step_artifacts/benchmark_job.txt << EOF Url: https://ci.linaro.org/job/tcwg-benchmark/$build_num Name: $(curl -s "https://ci.linaro.org/job/tcwg-benchmark/$build_num/api/json?tree=displayName" \ | jq -r ".displayName") EOF local build_status local build_ret while true; do # Ssh connection to ci.linaro.org occasionally drops. We need # to check whether benchmarking has finished, and, if not, continue # waiting. build_status=$(curl -s \ "https://ci.linaro.org/job/tcwg-benchmark/$build_num/api/json?tree=result" \ | jq -r ".result") case "$build_status" in "null") # Continue waiting true ;; "SUCCESS") build_ret=0 break ;; *) echo "# Benchmarking infra is offline:" \ >> ${rr[top_artifacts]}/results echo "-$EXTERNAL_FAIL" >> ${rr[top_artifacts]}/results build_ret=1 break ;; esac # Wait by following console output (ssh -p2222 -l $USER@linaro.org ci.linaro.org \ console tcwg-benchmark $build_num -f || true) \ | tee $run_step_artifacts/benchmark-wait.log done rm -rf "${rr[top_artifacts]}/annex" mkdir "${rr[top_artifacts]}/annex" ln -s "$results_dir" "${rr[top_artifacts]}/annex/bmk-data" return $build_ret ) } # Exit with code 0 if no regression compared to base-artifacts/. no_regression_p () { ( set -euf -o pipefail # check score-based regression no_build_regression_p "$@" # At this stage, there's no score-based regression. # We are now checking metric-based regression. assert_with_msg "Benchmarking succeeded, but bmk-data is missing" \ [ -e $run_step_top_artifacts/annex/bmk-data ] # Make sure there is no stray results.regression file, which we use # as failure marker. assert ! [ -f $run_step_artifacts/results.regressions ] local compare_opts="" case "${rr[target]}:$cflags" in "arm_eabi":*) compare_opts="--has_perf_logs no" ;; *) compare_opts="" ;; esac if [ -f /usr/lib/linux-tools/install-armhf-perf-workaround.sh ]; then # FIXME: # In some cases perf report crashes when run from armhf container on # ARMv8 machine. # Install a workaround while we are investigating the cause. sudo /usr/lib/linux-tools/install-armhf-perf-workaround.sh fi local new_results="${rr[top_artifacts]}/annex/bmk-data" local ref_results="base-artifacts/annex/bmk-data" assert_with_msg "Benchmarking succeeded, but no annex/bmk-data results" \ [ -d "$new_results" ] if ! [ -d "$ref_results" ]; then # base-artifacts has no reference results. # This can happen on init build (update_baseline=init). # In such cases we compare results to themselves just as an exercise. ref_results="$new_results" assert_with_msg "No reference results" \ [ "${rr[update_baseline]}" = "init" ] fi # Compare vs previous run mkdir -p ${rr[top_artifacts]}/results-vs-prev ln -s ../results-vs-prev $run_step_artifacts/results-vs-prev $scripts/tcwg-benchmark-results.sh \ --results_ref "$ref_results" ++results "$new_results" \ --top_artifacts "${rr[top_artifacts]}/results-vs-prev" \ --verbose $verbose --hw_tag "$(tcwg_bmk_hw)" \ $compare_opts \ > ${rr[top_artifacts]}/results-vs-prev/tcwg-benchmark-results.log 2>&1 & local res res=0 && wait $! || res=$? if [ $res != 0 ]; then return $EXTERNAL_FAIL fi # Below call to output-bmk-results.py creates *.regression files. assert_with_msg "Found stale regression files" \ [ x"$(find $run_step_artifacts/ -name "*.regression" | wc -l)" = x"0" ] # Extract 5 most recent compare-results-vs-prev-internal.csv files from # base-artifacts and compute std deviation out of them local -a csvs_paths csvs_paths=("results-vs-prev/compare-results-internal.csv" "$(basename $run_step_artifacts)/compare-results-vs-prev-internal.csv") local -a history_csvs local csv history_root="" while read csv; do if [ "$history_root" = "" ]; then history_root="$csv" continue fi history_csvs+=("$csv") done < <(get_git_history -0 base-artifacts "${csvs_paths[@]}") local csv tmpf local -a compare_results_list=() tmpf=$(mktemp) # FIXME: # To deal with some differences along base-artifacts recent history # - remove 'Failed for column' message from csv file # - skip emtpy csv files. for csv in "${history_csvs[@]}"; do grep -v 'Failed for column' "$csv" > "$tmpf" || true cp "$tmpf" "$csv" if [ -s "$csv" ]; then compare_results_list+=("$csv") fi done if [ ${#compare_results_list[@]} != 0 ]; then $scripts/../bmk-scripts/compute-variability.py \ --inputs "${compare_results_list[@]}" ${rr[top_artifacts]}/results-vs-prev/compare-results-internal.csv \ --weights linear --method avg \ --output ${rr[top_artifacts]}/results-vs-prev/bmk-specific-variability-avg.csv || true $scripts/../bmk-scripts/compute-variability.py \ --inputs "${compare_results_list[@]}" ${rr[top_artifacts]}/results-vs-prev/compare-results-internal.csv \ --weights 2-peaks-linear --method max \ --output ${rr[top_artifacts]}/results-vs-prev/bmk-specific-variability-max.csv || true fi rm -rf "$history_root" "$tmpf" $scripts/../bmk-scripts/output-bmk-results.py \ --compare_results ${rr[top_artifacts]}/results-vs-prev/compare-results-internal.csv \ --variability_file ${rr[top_artifacts]}/results-vs-prev/bmk-specific-variability-avg.csv \ --variability_file_data "avg" \ --run_step_dir "$run_step_artifacts"/ \ --metric "${rr[metric_id]}" --mode "${rr[mode]}" \ --details quiet > $run_step_artifacts/output-bmk-results.log # copy inputs useful to build the mail / jira / .. to mail dir for resfile in $run_step_artifacts/{exe,symbol}.{regression,improvement}; do if [ -f $resfile ]; then cp $resfile ${rr[top_artifacts]}/notify/ fi done # return status rely on the presence of the results.regressions file if [ -f $run_step_artifacts/results.regressions ]; then assert_with_msg "Found a regression while comparing the build against itself" \ [ "$ref_results" != "$new_results" ] return 1 fi return 0 ) } # Compiler changes tend to cause the most regressions. # Breakup updated components into compiler and the rest of components # to reduce the number of builds. case "${rr[toolchain]}" in llvm) rr[breakup_changed_components]="breakup_changed_components llvm" ;; gnu|gnu_eabi) rr[breakup_changed_components]="breakup_changed_components gcc" ;; *) assert false ;; esac run_step stop_on_fail -10 reset_artifacts case "${rr[toolchain]}" in gnu*) run_step stop_on_fail x prepare_abe run_step skip_on_fail -9 build_abe binutils run_step skip_on_fail -8 build_abe stage1 -- \ "${gcc_override_configure[@]}" run_step skip_on_fail x clean_sysroot case "${rr[components]}" in *glibc*) run_step skip_on_fail -7 build_abe linux run_step skip_on_fail -6 build_abe glibc ;; *newlib*) run_step skip_on_fail -6 build_abe newlib ;; esac run_step skip_on_fail -5 build_abe stage2 -- \ "${gcc_override_configure[@]}" ;; llvm) run_step skip_on_fail -3 build_bmk_llvm ;; esac run_step skip_on_fail 1 benchmark -- "$cflags" run_step reset_on_fail x check_regression trap "" EXIT