mirror of
https://github.com/actions/setup-java.git
synced 2026-07-30 09:10:01 +08:00
9f43141311
* Restore dependency and wrapper caches concurrently Run primary dependency and wrapper cache restores in parallel while preserving existing outputs and save semantics. Add unit and E2E coverage for concurrent restore behavior, wrapper cache validation, and additional-cache error handling. Include a manual benchmark workflow for baseline-vs-candidate restore timing comparisons across OSes. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d43ec3dd-96c7-4eb3-909e-b8123cd12d3c * Address PR review comments Use env variables for cache-hit values in benchmark record steps to avoid expression expansion in run commands, and rename E2E restore step labels for clarity. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d43ec3dd-96c7-4eb3-909e-b8123cd12d3c * Stabilize wrapper cache restore checks Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d43ec3dd-96c7-4eb3-909e-b8123cd12d3c
136 lines
4.1 KiB
Bash
136 lines
4.1 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
|
|
command=${1:?command is required}
|
|
tool=${2:?tool is required}
|
|
|
|
case "$tool" in
|
|
maven)
|
|
dependency_cache="$HOME/.m2/repository"
|
|
wrapper_cache="$HOME/.m2/wrapper/dists"
|
|
dependency_file="benchmark/pom.xml"
|
|
wrapper_file="benchmark/.mvn/wrapper/maven-wrapper.properties"
|
|
;;
|
|
gradle)
|
|
dependency_cache="$HOME/.gradle/caches"
|
|
wrapper_cache="$HOME/.gradle/wrapper"
|
|
dependency_file="benchmark/build.gradle"
|
|
wrapper_file="benchmark/gradle/wrapper/gradle-wrapper.properties"
|
|
;;
|
|
*)
|
|
echo "Unsupported tool: $tool" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
case "$command" in
|
|
prepare)
|
|
profile=${3:?profile is required}
|
|
mkdir -p "$(dirname "$dependency_file")" "$(dirname "$wrapper_file")"
|
|
printf '// setup-java cache benchmark v1: %s\n' "$profile" > "$dependency_file"
|
|
printf '# setup-java cache benchmark v1: %s\n' "$profile" > "$wrapper_file"
|
|
;;
|
|
reset)
|
|
rm -rf "$dependency_cache" "$wrapper_cache"
|
|
;;
|
|
populate)
|
|
profile=${3:?profile is required}
|
|
case "$profile" in
|
|
small)
|
|
dependency_megabytes=8
|
|
wrapper_megabytes=2
|
|
;;
|
|
large)
|
|
dependency_megabytes=128
|
|
wrapper_megabytes=32
|
|
;;
|
|
*)
|
|
echo "Unsupported profile: $profile" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
mkdir -p "$dependency_cache/setup-java-benchmark"
|
|
mkdir -p "$wrapper_cache/setup-java-benchmark"
|
|
dd if=/dev/urandom \
|
|
of="$dependency_cache/setup-java-benchmark/payload" \
|
|
bs=1048576 count="$dependency_megabytes" 2>/dev/null
|
|
dd if=/dev/urandom \
|
|
of="$wrapper_cache/setup-java-benchmark/payload" \
|
|
bs=1048576 count="$wrapper_megabytes" 2>/dev/null
|
|
;;
|
|
start)
|
|
node -e "require('fs').writeFileSync('.benchmark-start', String(Date.now()))"
|
|
;;
|
|
record)
|
|
os=${3:?os is required}
|
|
profile=${4:?profile is required}
|
|
implementation=${5:?implementation is required}
|
|
iteration=${6:?iteration is required}
|
|
cache_hit=${7:?cache-hit output is required}
|
|
if [ "$cache_hit" != "true" ]; then
|
|
echo "Expected an exact dependency-cache hit for $implementation" >&2
|
|
exit 1
|
|
fi
|
|
test -f "$dependency_cache/setup-java-benchmark/payload"
|
|
started=$(cat .benchmark-start)
|
|
finished=$(node -e "process.stdout.write(String(Date.now()))")
|
|
elapsed=$((finished - started))
|
|
mkdir -p .benchmark-results
|
|
printf '%s,%s,%s,%s,%s,%s\n' \
|
|
"$os" "$tool" "$profile" "$implementation" "$iteration" "$elapsed" \
|
|
>> .benchmark-results/timings.csv
|
|
;;
|
|
summarize)
|
|
summary_file=${3:?summary file is required}
|
|
results_file=".benchmark-results/timings.csv"
|
|
node --input-type=module - "$results_file" "$summary_file" <<'NODE'
|
|
import fs from 'node:fs';
|
|
|
|
const [, , resultsFile, summaryFile] = process.argv;
|
|
const rows = fs
|
|
.readFileSync(resultsFile, 'utf8')
|
|
.trim()
|
|
.split('\n')
|
|
.map(line => {
|
|
const [os, tool, profile, implementation, iteration, elapsed] =
|
|
line.split(',');
|
|
return {os, tool, profile, implementation, iteration, elapsed: +elapsed};
|
|
});
|
|
const average = implementation => {
|
|
const values = rows
|
|
.filter(row => row.implementation === implementation)
|
|
.map(row => row.elapsed);
|
|
if (values.length === 0) {
|
|
throw new Error(`No ${implementation} benchmark results were recorded`);
|
|
}
|
|
return Math.round(values.reduce((sum, value) => sum + value, 0) / values.length);
|
|
};
|
|
const baseline = average('baseline');
|
|
const candidate = average('candidate');
|
|
const change = (((candidate - baseline) / baseline) * 100).toFixed(1);
|
|
const {os, tool, profile} = rows[0];
|
|
const lines = [
|
|
`### ${tool} ${profile} cache restore on ${os}`,
|
|
'',
|
|
'| Implementation | Iteration | Wall time (ms) |',
|
|
'| --- | ---: | ---: |',
|
|
...rows.map(
|
|
row =>
|
|
`| ${row.implementation} | ${row.iteration} | ${row.elapsed} |`
|
|
),
|
|
`| **baseline average** | | **${baseline}** |`,
|
|
`| **candidate average** | | **${candidate}** |`,
|
|
'',
|
|
`Candidate change from baseline: **${change}%**`,
|
|
''
|
|
];
|
|
fs.appendFileSync(summaryFile, `${lines.join('\n')}\n`);
|
|
NODE
|
|
;;
|
|
*)
|
|
echo "Unsupported command: $command" >&2
|
|
exit 1
|
|
;;
|
|
esac
|