diff --git a/.github/workflows/reports.yml b/.github/workflows/reports.yml index d37f69e52d2..b1b747f5b96 100644 --- a/.github/workflows/reports.yml +++ b/.github/workflows/reports.yml @@ -69,7 +69,7 @@ jobs: - name: Build list of projects id: get_bench_projects run: | - PROJECTS=$(yq ./.github/benchmark_projects.yml -o json | jq -c '.projects | map(.)') + PROJECTS=$(yq ./.github/benchmark_projects.yml -o json | jq -c '.projects | to_entries | map(.value + { name: .key })') echo "projects=$PROJECTS" echo "projects=$PROJECTS" >> $GITHUB_OUTPUT @@ -294,49 +294,7 @@ jobs: retention-days: 3 overwrite: true - generate_compilation_and_execution_report: - name: Compilation and execution time - needs: [build-nargo] - runs-on: ubuntu-22.04 - timeout-minutes: 20 - permissions: - pull-requests: write - - steps: - - uses: actions/checkout@v4 - - - name: Download nargo binary - uses: ./.github/actions/download-nargo - - - name: Generate Compilation report - working-directory: ./test_programs - run: | - ./compilation_report.sh 0 1 - mv compilation_report.json ../compilation_report.json - - - name: Generate Execution report - working-directory: ./test_programs - run: | - ./execution_report.sh 0 1 - mv execution_report.json ../execution_report.json - - - name: Upload compilation report - uses: actions/upload-artifact@v4 - with: - name: in_progress_compilation_report - path: compilation_report.json - retention-days: 3 - overwrite: true - - - name: Upload execution report - uses: actions/upload-artifact@v4 - with: - name: in_progress_execution_report - path: execution_report.json - retention-days: 3 - overwrite: true - - external_repo_compilation_and_execution_report: + external_repo_reports: needs: [build-nargo, benchmark-projects-list] runs-on: ubuntu-22.04 timeout-minutes: 15 @@ -349,17 +307,12 @@ jobs: steps: - uses: actions/checkout@v4 with: - path: scripts sparse-checkout: | .github/actions/download-nargo/action.yml - test_programs/compilation_report.sh - test_programs/execution_report.sh - test_programs/parse_time.sh + scripts/gather_benchmark_data.sh + scripts/process_benchmark_data.sh sparse-checkout-cone-mode: false - - name: Download nargo binary - uses: ./scripts/.github/actions/download-nargo - - name: Checkout uses: actions/checkout@v4 with: @@ -367,33 +320,35 @@ jobs: path: test-repo ref: ${{ matrix.ref }} - - name: Fetch noir dependencies - working-directory: ./test-repo/${{ matrix.path }} - run: | - # We run `nargo check` to pre-fetch any dependencies so we don't measure the time to download these - # when benchmarking. - nargo check + - name: Download nargo binary + uses: ./.github/actions/download-nargo - name: Generate compilation report id: compilation_report - working-directory: ./test-repo/${{ matrix.path }} run: | - mv /home/runner/work/noir/noir/scripts/test_programs/compilation_report.sh ./compilation_report.sh - touch parse_time.sh - chmod +x parse_time.sh - cp /home/runner/work/noir/noir/scripts/test_programs/parse_time.sh ./parse_time.sh - ./compilation_report.sh 1 ${{ matrix.num_runs }} - - PACKAGE_NAME=${{ matrix.path }} - PACKAGE_NAME=$(basename $PACKAGE_NAME) - REPORT_NAME=compilation_report_$PACKAGE_NAME.json + PACKAGE_NAME=$(basename ${{ matrix.path }}) + REPORT_NAME=external_report_$PACKAGE_NAME.json REPORT_PATH=$(pwd)/$REPORT_NAME - mv ./compilation_report.json $REPORT_PATH echo "report_name=$REPORT_NAME" >> $GITHUB_OUTPUT echo "report_path=$REPORT_PATH" >> $GITHUB_OUTPUT + + - name: Generate report data + run: ./scripts/gather_benchmark_data.sh env: - FLAGS: ${{ matrix.flags }} + REPO_SLUG: ${{ matrix.repo }} + PROJECT_TAG: ${{ matrix.ref }} + REPO_DIR: test-repo + PROJECT_DIR: ${{ matrix.path }} + OUTPUT_DIR: ${{ github.workspace }}/output + NUM_RUNS: ${{ matrix.num_runs }} + + - name: Process report data + run: | + ./scripts/process_benchmark_data.sh $INPUT_DIR > ${{ steps.compilation_report.outputs.report_path }} + env: + INPUT_DIR: ${{ github.workspace }}/output + PROJECT_NAME: ${{ matrix.name }} - name: Upload compilation report uses: actions/upload-artifact@v4 @@ -403,36 +358,9 @@ jobs: retention-days: 3 overwrite: true - - name: Generate execution report - id: execution_report - working-directory: ./test-repo/${{ matrix.path }} - if: ${{ !matrix.cannot_execute }} - run: | - mv /home/runner/work/noir/noir/scripts/test_programs/execution_report.sh ./execution_report.sh - mv /home/runner/work/noir/noir/scripts/test_programs/parse_time.sh ./parse_time.sh - ./execution_report.sh 1 ${{ matrix.num_runs }} - - PACKAGE_NAME=${{ matrix.path }} - PACKAGE_NAME=$(basename $PACKAGE_NAME) - REPORT_NAME=execution_report_$PACKAGE_NAME.json - REPORT_PATH=$(pwd)/$REPORT_NAME - mv ./execution_report.json $REPORT_PATH - - echo "report_name=$REPORT_NAME" >> $GITHUB_OUTPUT - echo "report_path=$REPORT_PATH" >> $GITHUB_OUTPUT - - - name: Upload execution report - if: ${{ !matrix.cannot_execute }} - uses: actions/upload-artifact@v4 - with: - name: ${{ steps.execution_report.outputs.report_name }} - path: ${{ steps.execution_report.outputs.report_path }} - retention-days: 3 - overwrite: true - - name: Check compilation time limit run: | - TIME=$(jq '.[0].value' ${{ steps.compilation_report.outputs.report_path }}) + TIME=$(jq '.compilation_time.value' ${{ steps.compilation_report.outputs.report_path }}) TIME_LIMIT=${{ matrix.compilation-timeout }} if awk 'BEGIN{exit !(ARGV[1]>ARGV[2])}' "$TIME" "$TIME_LIMIT"; then # Don't bump this timeout without understanding why this has happened and confirming that you're not the cause. @@ -445,7 +373,7 @@ jobs: - name: Check execution time limit if: ${{ !matrix.cannot_execute }} run: | - TIME=$(jq '.[0].value' ${{ steps.execution_report.outputs.report_path }}) + TIME=$(jq '.execution_time.value' ${{ steps.execution_report.outputs.report_path }}) TIME_LIMIT=${{ matrix.execution-timeout }} if awk 'BEGIN{exit !(ARGV[1]>ARGV[2])}' "$TIME" "$TIME_LIMIT"; then # Don't bump this timeout without understanding why this has happened and confirming that you're not the cause. @@ -563,11 +491,11 @@ jobs: exit 1 fi - upload_compilation_report: - name: Upload compilation report - needs: [generate_compilation_and_execution_report, external_repo_compilation_and_execution_report] + upload_compilation_reports: + name: Upload compilation reports + needs: [external_repo_reports] timeout-minutes: 5 - # We want this job to run even if one variation of the matrix in `external_repo_compilation_and_execution_report` fails + # We want this job to run even if one variation of the matrix in `external_repo_reports` fails if: always() runs-on: ubuntu-22.04 permissions: @@ -580,16 +508,10 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Download initial compilation report - uses: actions/download-artifact@v4 - with: - name: in_progress_compilation_report - path: ./reports - - name: Download matrix compilation reports uses: actions/download-artifact@v4 with: - pattern: compilation_report_* + pattern: external_report_* path: ./reports merge-multiple: true @@ -597,7 +519,7 @@ jobs: run: | # Github actions seems to not expand "**" in globs by default. shopt -s globstar - jq --slurp '. | flatten' ./reports/* | tee time_bench.json + jq --slurp 'map(.compilation_time | select(.))' ./reports/* | tee time_bench.json - name: Store benchmark result uses: benchmark-action/github-action-benchmark@4de1bed97a47495fc4c5404952da0499e31f5c29 @@ -615,11 +537,11 @@ jobs: alert-comment-cc-users: "@TomAFrench" max-items-in-chart: 50 - upload_compilation_memory_report: - name: Upload compilation memory report - needs: [generate_memory_report, external_repo_memory_report] + upload_execution_reports: + name: Upload execution reports + needs: [external_repo_reports] timeout-minutes: 5 - # We want this job to run even if one variation of the matrix in `external_repo_memory_report` fails + # We want this job to run even if one variation of the matrix in `external_repo_reports` fails if: always() runs-on: ubuntu-22.04 permissions: @@ -632,30 +554,71 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Download initial memory report + - name: Download matrix compilation reports uses: actions/download-artifact@v4 with: - name: in_progress_compilation_mem_report + pattern: external_report_* + path: ./reports + merge-multiple: true - - name: Download matrix memory reports + - name: Merge execution reports using jq + run: | + # Github actions seems to not expand "**" in globs by default. + shopt -s globstar + jq --slurp 'map(.execution_time | select(.))' ./reports/* | tee time_bench.json + + - name: Store benchmark result + uses: benchmark-action/github-action-benchmark@4de1bed97a47495fc4c5404952da0499e31f5c29 + with: + name: "Execution Time" + tool: "customSmallerIsBetter" + output-file-path: ./time_bench.json + github-token: ${{ secrets.GITHUB_TOKEN }} + # We want this to only run on master to avoid garbage data from PRs being added. + auto-push: ${{ github.ref == 'refs/heads/master' }} + alert-threshold: "120%" + comment-on-alert: true + comment-always: ${{ contains( github.event.pull_request.labels.*.name, 'bench-show') }} + fail-on-alert: false + alert-comment-cc-users: "@TomAFrench" + max-items-in-chart: 50 + + upload_artifact_reports: + name: Upload artifact reports + needs: [external_repo_reports] + timeout-minutes: 5 + # We want this job to run even if one variation of the matrix in `external_repo_reports` fails + if: always() + runs-on: ubuntu-22.04 + permissions: + pull-requests: write + # deployments permission to deploy GitHub pages website + deployments: write + # contents permission to update benchmark contents in gh-pages branch + contents: write + + steps: + - uses: actions/checkout@v4 + + - name: Download matrix compilation reports uses: actions/download-artifact@v4 with: - pattern: compilation_mem_report_* + pattern: external_report_* path: ./reports merge-multiple: true - - name: Merge memory reports using jq + - name: Merge artifact size reports using jq run: | # Github actions seems to not expand "**" in globs by default. shopt -s globstar - jq --slurp '. | flatten' ./reports/* | tee memory_bench.json + jq --slurp 'map(.artifact_size | select(.))' ./reports/* | tee artifact_size.json - name: Store benchmark result uses: benchmark-action/github-action-benchmark@4de1bed97a47495fc4c5404952da0499e31f5c29 with: - name: "Compilation Memory" + name: "Artifact Size" tool: "customSmallerIsBetter" - output-file-path: ./memory_bench.json + output-file-path: ./artifact_size.json github-token: ${{ secrets.GITHUB_TOKEN }} # We want this to only run on master to avoid garbage data from PRs being added. auto-push: ${{ github.ref == 'refs/heads/master' }} @@ -666,8 +629,8 @@ jobs: alert-comment-cc-users: "@TomAFrench" max-items-in-chart: 50 - upload_execution_memory_report: - name: Upload execution memory report + upload_compilation_memory_report: + name: Upload compilation memory report needs: [generate_memory_report, external_repo_memory_report] timeout-minutes: 5 # We want this job to run even if one variation of the matrix in `external_repo_memory_report` fails @@ -686,12 +649,12 @@ jobs: - name: Download initial memory report uses: actions/download-artifact@v4 with: - name: in_progress_execution_mem_report + name: in_progress_compilation_mem_report - name: Download matrix memory reports uses: actions/download-artifact@v4 with: - pattern: execution_mem_report_* + pattern: compilation_mem_report_* path: ./reports merge-multiple: true @@ -704,7 +667,7 @@ jobs: - name: Store benchmark result uses: benchmark-action/github-action-benchmark@4de1bed97a47495fc4c5404952da0499e31f5c29 with: - name: "Execution Memory" + name: "Compilation Memory" tool: "customSmallerIsBetter" output-file-path: ./memory_bench.json github-token: ${{ secrets.GITHUB_TOKEN }} @@ -717,11 +680,11 @@ jobs: alert-comment-cc-users: "@TomAFrench" max-items-in-chart: 50 - upload_execution_report: - name: Upload execution report - needs: [generate_compilation_and_execution_report, external_repo_compilation_and_execution_report] + upload_execution_memory_report: + name: Upload execution memory report + needs: [generate_memory_report, external_repo_memory_report] timeout-minutes: 5 - # We want this job to run even if one variation of the matrix in `external_repo_compilation_and_execution_report` fails + # We want this job to run even if one variation of the matrix in `external_repo_memory_report` fails if: always() runs-on: ubuntu-22.04 permissions: @@ -734,30 +697,30 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Download initial execution report + - name: Download initial memory report uses: actions/download-artifact@v4 with: - name: in_progress_execution_report + name: in_progress_execution_mem_report - - name: Download matrix execution reports + - name: Download matrix memory reports uses: actions/download-artifact@v4 with: - pattern: execution_report_* + pattern: execution_mem_report_* path: ./reports merge-multiple: true - - name: Merge execution reports using jq + - name: Merge memory reports using jq run: | # Github actions seems to not expand "**" in globs by default. shopt -s globstar - jq --slurp '. | flatten' ./reports/* | tee time_bench.json + jq --slurp '. | flatten' ./reports/* | tee memory_bench.json - name: Store benchmark result uses: benchmark-action/github-action-benchmark@4de1bed97a47495fc4c5404952da0499e31f5c29 with: - name: "Execution Time" + name: "Execution Memory" tool: "customSmallerIsBetter" - output-file-path: ./time_bench.json + output-file-path: ./memory_bench.json github-token: ${{ secrets.GITHUB_TOKEN }} # We want this to only run on master to avoid garbage data from PRs being added. auto-push: ${{ github.ref == 'refs/heads/master' }} @@ -778,9 +741,10 @@ jobs: if: ${{ always() }} needs: - rust_benchmarks - - upload_compilation_report + - upload_compilation_reports + - upload_execution_reports + - upload_artifact_reports - upload_compilation_memory_report - - upload_execution_report - upload_execution_memory_report steps: diff --git a/scripts/gather_benchmark_data.sh b/scripts/gather_benchmark_data.sh new file mode 100755 index 00000000000..3f8686e733d --- /dev/null +++ b/scripts/gather_benchmark_data.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +set -ue + +NARGO=${NARGO:-nargo} +OUTPUT_DIR=$(realpath ${OUTPUT_DIR:-"$(dirname "$0")/output")}) +mkdir -p $OUTPUT_DIR + +echo "PROJECT_TAG: ${PROJECT_TAG}" +echo "PROJECT_DIR: ${PROJECT_DIR}" + +setup_repo() { + local repo_slug=$1 + local repo_tag=$2 + local temp_dir=$3 + + local repo_url="https://github.com/$repo_slug" + + # Sadly we cannot use depth=1 clones here as we need to be able to checkout + # commit hashes as well as branches/releases + git clone $repo_url $temp_dir + git -C $temp_dir -c advice.detachedHead=false checkout $repo_tag +} + +compile_project() { + echo "Compiling program" + for ((i = 1; i <= NUM_RUNS; i++)); do + NOIR_LOG=trace NARGO_LOG_DIR=./tmp $NARGO compile --force --silence-warnings 2>> /dev/null + done + + mv ./tmp/* $OUTPUT_DIR/compilation.jsonl +} + +execute_project() { + echo "Executing program" + for ((i = 1; i <= NUM_RUNS; i++)); do + NOIR_LOG=trace NARGO_LOG_DIR=./tmp $NARGO execute --silence-warnings >> /dev/null + done + + mv ./tmp/* $OUTPUT_DIR/execution.jsonl +} + +save_artifact() { + echo "Copying artifact" + mv ./target/*.json $OUTPUT_DIR/artifact.json +} + +if [ -z "${REPO_DIR:-}" ]; then + TMP_DIR=$(mktemp -d) + trap "rm -rf $TMP_DIR" EXIT + + setup_repo $REPO_SLUG $PROJECT_TAG $TMP_DIR +fi + +REPO_DIR=${REPO_DIR:-$TMP_DIR} +cd "$REPO_DIR/$PROJECT_DIR" + +[[ -f ./Prover.toml ]] && HAS_PROVER_INPUTS=true + +# We run `nargo check` to pre-fetch any dependencies so we don't measure the time to download these +# when benchmarking. +$NARGO check --silence-warnings + +compile_project +if [ "${HAS_PROVER_INPUTS:-"false"}" == "true" ]; then + execute_project +fi +save_artifact + +echo "Completed gathering benchmarks" diff --git a/scripts/process_benchmark_data.sh b/scripts/process_benchmark_data.sh new file mode 100755 index 00000000000..d34450f0cbd --- /dev/null +++ b/scripts/process_benchmark_data.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +set -ue + +INPUT_DIR=$(realpath $1) + +average_times() { + awk -v RS=" " ' + function parse_time(value) { + micro_seconds = match($1, /µs$/); + if (micro_seconds != 0) { + current_time = substr($1, 0, micro_seconds) + return current_time / 1000000; + } + milli_seconds = match($1, /ms$/); + if (milli_seconds != 0) { + current_time = substr($1, 0, milli_seconds) + return current_time / 1000; + } + seconds = match($1, /s$/); + if (seconds != 0) { + current_time = substr($1, 0, seconds) + return current_time; + } + + printf "Could not parse time: %" $1 > "/dev/stderr" + + printf "ERROR" + exit 1 + } + + { + seconds = parse_time($1); + sum += seconds; + n++; + } + END { + if (n > 0) + printf "%.3f\n", sum / n + else + printf "%.3f\n", 0 + }' <<<${@} +} + +compilation_time() { + TIMES=($(jq -r '. | select(.target == "nargo::cli" and .fields.message == "close") | .fields."time.busy"' "$INPUT_DIR/compilation.jsonl")) + + AVG_TIME=$(average_times "${TIMES[@]}") + + jq -rc "{name: \"$PROJECT_NAME\", metric: \"compilation_time\", value: \""$AVG_TIME"\" | tonumber, unit: \"s\"}" --null-input +} + +execution_time() { + TIMES=($(jq -r '. | select(.target == "nargo::ops::execute" and .fields.message == "close") | .fields."time.busy"' "$INPUT_DIR/execution.jsonl")) + + AVG_TIME=$(average_times "${TIMES[@]}") + + jq -rc "{name: \"$PROJECT_NAME\", metric: \"execution_time\", value: \""$AVG_TIME"\" | tonumber, unit: \"s\"}" --null-input +} + +artifact_size() { + ARTIFACT_SIZE=$(wc -c <"$INPUT_DIR/artifact.json" | awk '{printf "%.1f\n", $1/1000}') + + jq -rc "{name: \"$PROJECT_NAME\", metric: \"artifact_size\", value: \""$ARTIFACT_SIZE"\" | tonumber, unit: \"KB\"}" --null-input +} + +jq --slurp 'reduce .[] as $i ({}; .[$i.metric] = ($i | del(.metric)))' <<< "$(compilation_time)$(execution_time)$(artifact_size)" diff --git a/test_programs/compilation_report.sh b/test_programs/compilation_report.sh deleted file mode 100755 index 22b1f2a52ce..00000000000 --- a/test_programs/compilation_report.sh +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env bash -set -e - -PARSE_TIME=$(realpath "$(dirname "$0")/parse_time.sh") -current_dir=$(pwd) -base_path="$current_dir/execution_success" - -# Tests to be profiled for compilation report -tests_to_profile=("regression_4709" "ram_blowup_regression" "global_var_regression_entry_points") - -echo "[ " > $current_dir/compilation_report.json - -# If there is an argument that means we want to generate a report for only the current directory -if [ "$1" == "1" ]; then - base_path="$current_dir" - tests_to_profile=(".") -fi - -ITER="1" -NUM_ARTIFACTS=${#tests_to_profile[@]} -FLAGS=${FLAGS:- ""} - -for dir in ${tests_to_profile[@]}; do - if [[ " ${excluded_dirs[@]} " =~ " ${dir} " ]]; then - continue - fi - - if [[ ${CI-false} = "true" ]] && [[ " ${ci_excluded_dirs[@]} " =~ " ${dir} " ]]; then - continue - fi - - cd $base_path/$dir - - # The default package to run is the supplied list hardcoded at the top of the script - PACKAGE_NAME=$dir - # Otherwise default to the current directory as the package we want to run - if [ "$1" == "1" ]; then - PACKAGE_NAME=$(basename $current_dir) - fi - - NUM_RUNS=$2 - TOTAL_TIME=0 - - for ((i = 1; i <= NUM_RUNS; i++)); do - NOIR_LOG=trace NARGO_LOG_DIR=./tmp nargo compile --force --pedantic-solving --silence-warnings $FLAGS - done - - TIMES=($(jq -r '. | select(.target == "nargo::cli" and .fields.message == "close") | .fields."time.busy"' ./tmp/*)) - - AVG_TIME=$(awk -v RS=" " -v parse_time="$PARSE_TIME" ' - { - # Times are formatted annoyingly so we need to parse it. - parse_time" "$1 | getline current_time - close(parse_time" "$1) - sum += current_time; - n++; - } - END { - if (n > 0) - printf "%.3f\n", sum / n - else - printf "%.3f\n", 0 - }' <<<"${TIMES[@]}") - - jq -rc "{name: \"$PACKAGE_NAME\", value: \""$AVG_TIME"\" | tonumber, unit: \"s\"}" --null-input >> $current_dir/compilation_report.json - - if (($ITER != $NUM_ARTIFACTS)); then - echo "," >> $current_dir/compilation_report.json - fi - - rm -rf ./tmp - - ITER=$(( $ITER + 1 )) -done - -echo "]" >> $current_dir/compilation_report.json diff --git a/test_programs/execution_report.sh b/test_programs/execution_report.sh deleted file mode 100755 index 3adfabd6075..00000000000 --- a/test_programs/execution_report.sh +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/env bash -set -e - -PARSE_TIME=$(realpath "$(dirname "$0")/parse_time.sh") -current_dir=$(pwd) -base_path="$current_dir/execution_success" - -# Tests to be profiled for execution report -tests_to_profile=("regression_4709" "ram_blowup_regression" "global_var_regression_entry_points") - -echo "[" > $current_dir/execution_report.json - -# If there is an argument that means we want to generate a report for only the current directory -if [ "$1" == "1" ]; then - base_path="$current_dir" - tests_to_profile=(".") -fi - -ITER="1" -NUM_ARTIFACTS=${#tests_to_profile[@]} - -for dir in ${tests_to_profile[@]}; do - if [[ " ${excluded_dirs[@]} " =~ " ${dir} " ]]; then - continue - fi - - if [[ ${CI-false} = "true" ]] && [[ " ${ci_excluded_dirs[@]} " =~ " ${dir} " ]]; then - continue - fi - - cd $base_path/$dir - - # The default package to run is the supplied list hardcoded at the top of the script - PACKAGE_NAME=$dir - # Otherwise default to the current directory as the package we want to run - if [ "$1" == "1" ]; then - PACKAGE_NAME=$(basename $current_dir) - fi - - # Check whether a compilation artifact exists. - # Any programs part of this benchmark should already be compiled. - # We want to make sure that compilation time is not included in the execution time. - if [ ! -e ./target/*.json ]; then - echo "Missing compilation artifact for $PACKAGE_NAME" - exit 1 - fi - - - NUM_RUNS=$2 - TOTAL_TIME=0 - - for ((i = 1; i <= NUM_RUNS; i++)); do - NOIR_LOG=trace NARGO_LOG_DIR=./tmp nargo execute --pedantic-solving --silence-warnings - done - - TIMES=($(jq -r '. | select(.target == "nargo::ops::execute" and .fields.message == "close") | .fields."time.busy"' ./tmp/*)) - - AVG_TIME=$(awk -v RS=" " -v parse_time="$PARSE_TIME" ' - { - # Times are formatted annoyingly so we need to parse it. - parse_time" "$1 | getline current_time - close(parse_time" "$1) - sum += current_time; - n++; - } - END { - if (n > 0) - printf "%.3f\n", sum / n - else - printf "%.3f\n", 0 - }' <<<"${TIMES[@]}") - - jq -rc "{name: \"$PACKAGE_NAME\", value: \""$AVG_TIME"\" | tonumber, unit: \"s\"}" --null-input >> $current_dir/execution_report.json - - if (($ITER != $NUM_ARTIFACTS)); then - echo "," >> $current_dir/execution_report.json - fi - - rm -rf ./tmp - - ITER=$(( $ITER + 1 )) -done - -echo "]" >> $current_dir/execution_report.json