Skip to content

Include realized build time savings in experiment summary #261

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Mar 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
361d0d0
Rename Build Caching Leverage to Performance Characteristics
erichaagdev Dec 23, 2022
53fd8d7
Update many function names to use performance characteristics
erichaagdev Dec 23, 2022
1e66ce1
Return effective task execution time from API tool
erichaagdev Dec 23, 2022
4a90d31
Print realized build time savings in results
erichaagdev Dec 23, 2022
08843d9
Print performance characteristics header in separate function
erichaagdev Dec 28, 2022
056fafb
Change printed format of realized build time savings
erichaagdev Dec 28, 2022
1897984
Make static variable final
erichaagdev Dec 28, 2022
c49a38a
Change data type of effectiveTaskExecutionDuration to Duration
erichaagdev Dec 28, 2022
30bced9
Return all durations as milliseconds
erichaagdev Dec 28, 2022
83dca39
Format caching leverage metrics as durations
erichaagdev Dec 28, 2022
8786e84
Remove nullability annotations
erichaagdev Dec 28, 2022
2a0fcff
Change comment wording
erichaagdev Dec 28, 2022
9bfabd1
Shorten variable names
erichaagdev Dec 28, 2022
c4c8ad1
Update changes.md
erichaagdev Dec 28, 2022
713c5be
Revert "Format caching leverage metrics as durations"
erichaagdev Dec 28, 2022
6b663fd
Revert "Return all durations as milliseconds"
erichaagdev Dec 28, 2022
c1d8a1a
Only print realized build time savings when effective task execution …
erichaagdev Dec 28, 2022
2933aed
Increase number of dashes below Performance Characteristics
erichaagdev Mar 6, 2023
01c8518
Merge branch 'main' into erichaagdev/display-realized-build-time-savings
erichaagdev Mar 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ public BuildValidationData fetchBuildValidationData(String buildScanId) {
attributes.getRequestedTasks(),
buildOutcomeFrom(attributes),
remoteBuildCacheUrlFrom(buildCachePerformance),
summarizeTaskExecutions(buildCachePerformance)
summarizeTaskExecutions(buildCachePerformance),
toDuration(buildCachePerformance.getEffectiveTaskExecutionTime())
);
}
if (build.getBuildToolType().equalsIgnoreCase("maven")) {
Expand All @@ -132,7 +133,8 @@ public BuildValidationData fetchBuildValidationData(String buildScanId) {
attributes.getRequestedGoals(),
buildOutcomeFrom(attributes),
remoteBuildCacheUrlFrom(buildCachePerformance),
summarizeTaskExecutions(buildCachePerformance)
summarizeTaskExecutions(buildCachePerformance),
toDuration(buildCachePerformance.getEffectiveProjectExecutionTime())
);
}
throw new UnknownBuildAgentException(baseUrl, buildScanId, build.getBuildToolType());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Path;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -105,7 +106,8 @@ private BuildValidationData fetchBuildScanData(int index, URL buildScanUrl, Cust
Collections.emptyList(),
"",
null,
Collections.emptyMap());
Collections.emptyMap(),
Duration.ZERO);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public enum Fields {
EXECUTED_CACHEABLE_DURATION("Executed cacheable duration", d -> totalDuration(d, "executed_cacheable")),
EXECUTED_NOT_CACHEABLE("Executed not cacheable", d -> totalTasks(d, "executed_not_cacheable")),
EXECUTED_NOT_CACHEABLE_DURATION("Executed not cacheable duration", d -> totalDuration(d, "executed_not_cacheable")),
EFFECTIVE_TASK_EXECUTION_DURATION("Effective task execution duration", d -> String.valueOf(d.getEffectiveTaskExecutionDuration().toMillis())),
;

public final String label;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

import java.net.MalformedURLException;
import java.net.URL;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class BuildValidationData {
private static Pattern REMOTE_BUILD_CACHE_SHARD_PATTERN = Pattern.compile(".*/cache/(.+)$");
private static final Pattern REMOTE_BUILD_CACHE_SHARD_PATTERN = Pattern.compile(".*/cache/(.+)$");

private final String rootProjectName;
private final String buildScanId;
Expand All @@ -20,8 +21,20 @@ public class BuildValidationData {
private final String buildOutcome;
private final URL remoteBuildCacheUrl;
private final Map<String, TaskExecutionSummary> tasksByAvoidanceOutcome;

public BuildValidationData(String rootProjectName, String buildScanId, URL gradleEnterpriseServerUrl, String gitUrl, String gitBranch, String gitCommitId, List<String> requestedTasks, String buildOutcome, URL remoteBuildCacheUrl, Map<String, TaskExecutionSummary> tasksByAvoidanceOutcome) {
private final Duration effectiveTaskExecutionDuration;

public BuildValidationData(
String rootProjectName,
String buildScanId,
URL gradleEnterpriseServerUrl,
String gitUrl,
String gitBranch,
String gitCommitId,
List<String> requestedTasks,
String buildOutcome,
URL remoteBuildCacheUrl,
Map<String, TaskExecutionSummary> tasksByAvoidanceOutcome,
Duration effectiveTaskExecutionDuration) {
this.rootProjectName = rootProjectName;
this.buildScanId = buildScanId;
this.gradleEnterpriseServerUrl = gradleEnterpriseServerUrl;
Expand All @@ -32,6 +45,7 @@ public BuildValidationData(String rootProjectName, String buildScanId, URL gradl
this.buildOutcome = buildOutcome;
this.remoteBuildCacheUrl = remoteBuildCacheUrl;
this.tasksByAvoidanceOutcome = tasksByAvoidanceOutcome;
this.effectiveTaskExecutionDuration = effectiveTaskExecutionDuration;
}

public String getRootProjectName() {
Expand Down Expand Up @@ -124,4 +138,8 @@ private static boolean isFound(String value) {
public Map<String, TaskExecutionSummary> getTasksByAvoidanceOutcome() {
return tasksByAvoidanceOutcome;
}

public Duration getEffectiveTaskExecutionDuration() {
return effectiveTaskExecutionDuration;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ fetch_build_cache_metrics() {

# Overrides info.sh#print_performance_metrics
print_performance_metrics() {
print_build_caching_leverage_metrics
print_performance_characteristics
}

print_quick_links() {
Expand Down Expand Up @@ -313,7 +313,7 @@ two build scans that were published as part of running the experiment. The build
scan of the second build is particularly interesting since this is where you can
inspect what tasks were not leveraging the local build cache.

$(explain_build_cache_leverage)
$(explain_performance_characteristics)

The ‘Investigation Quick Links’ section below allows quick navigation to the
most relevant views in build scans to investigate what tasks were avoided due to
Expand All @@ -335,7 +335,7 @@ The ‘Summary’ section below captures the configuration of the experiment. No
build scans are available for inspection since publishing was disabled for the
experiment.

$(explain_build_cache_leverage)
$(explain_performance_characteristics)

$(explain_command_to_repeat_experiment)

Expand All @@ -349,12 +349,13 @@ EOF
print_wizard_text "${text}"
}

explain_build_cache_leverage() {
explain_performance_characteristics() {
local text
IFS='' read -r -d '' text <<EOF
The ‘Build Caching Leverage’ section below reveals the realized and potential
savings from build caching. All cacheable tasks' outputs need to be taken from
the build cache in the second build for the build to be fully cacheable.
The ‘Performance Characteristics’ section below reveals the realized and
potential savings from build caching. All cacheable tasks' outputs need to be
taken from the build cache in the second build for the build to be fully
cacheable.
EOF
echo -n "${text}"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ fetch_build_cache_metrics() {

# Overrides info.sh#print_performance_metrics
print_performance_metrics() {
print_build_caching_leverage_metrics
print_performance_characteristics
}

print_quick_links() {
Expand Down Expand Up @@ -352,7 +352,7 @@ two build scans that were published as part of running the experiment. The build
scan of the second build is particularly interesting since this is where you can
inspect what tasks were not leveraging the local build cache.

$(explain_build_cache_leverage)
$(explain_performance_characteristics)

The ‘Investigation Quick Links’ section below allows quick navigation to the
most relevant views in build scans to investigate what tasks were avoided due to
Expand All @@ -374,7 +374,7 @@ The ‘Summary’ section below captures the configuration of the experiment. No
build scans are available for inspection since publishing was disabled for the
experiment.

$(explain_build_cache_leverage)
$(explain_performance_characteristics)

$(explain_command_to_repeat_experiment)

Expand All @@ -388,12 +388,13 @@ EOF
print_wizard_text "${text}"
}

explain_build_cache_leverage() {
explain_performance_characteristics() {
local text
IFS='' read -r -d '' text <<EOF
The ‘Build Caching Leverage’ section below reveals the realized and potential
savings from build caching. All cacheable tasks' outputs need to be taken from
the build cache in the second build for the build to be fully cacheable.
The ‘Performance Characteristics’ section below reveals the realized and
potential savings from build caching. All cacheable tasks' outputs need to be
taken from the build cache in the second build for the build to be fully
cacheable.
EOF
echo -n "${text}"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ print_experiment_specific_summary_info() {

# Overrides info.sh#print_performance_metrics
print_performance_metrics() {
print_build_caching_leverage_metrics
print_performance_characteristics
}

print_quick_links() {
Expand Down Expand Up @@ -342,9 +342,10 @@ two build scans that were published as part of running the experiment. The build
scan of the second build is particularly interesting since this is where you can
inspect what tasks were not leveraging Gradle’s remote build cache.

The ‘Build Caching Leverage’ section below reveals the realized and potential
savings from build caching. All cacheable tasks' outputs need to be taken from
the build cache in the second build for the build to be fully cacheable.
The ‘Performance Characteristics’ section below reveals the realized and
potential savings from build caching. All cacheable tasks' outputs need to be
taken from the build cache in the second build for the build to be fully
cacheable.

The ‘Investigation Quick Links’ section below allows quick navigation to the
most relevant views in build scans to investigate what tasks were avoided due to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ fetch_build_cache_metrics() {

# Overrides info.sh#print_performance_metrics
print_performance_metrics() {
print_build_caching_leverage_metrics
print_performance_characteristics
}

print_quick_links() {
Expand Down Expand Up @@ -513,9 +513,10 @@ two build scans that were published as part of running the experiment. The build
scan of the second build is particularly interesting since this is where you can
inspect what tasks were not leveraging Gradle’s remote build cache.

The ‘Build Caching Leverage’ section below reveals the realized and potential
savings from build caching. All cacheable tasks' outputs need to be taken from
the build cache in the second build for the build to be fully cacheable.
The ‘Performance Characteristics’ section below reveals the realized and
potential savings from build caching. All cacheable tasks' outputs need to be
taken from the build cache in the second build for the build to be fully
cacheable.

The ‘Investigation Quick Links’ section below allows quick navigation to the
most relevant views in build scans to investigate what tasks were avoided due to
Expand Down
10 changes: 9 additions & 1 deletion components/scripts/lib/build-scan-parse.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ executed_cacheable_duration=()
executed_not_cacheable_num_tasks=()
executed_not_cacheable_duration=()

# Build duration metrics
effective_task_execution_duration=()

parse_build_scan_csv() {
# This isn't the most robust way to read a CSV,
# but we control the CSV so we don't have to worry about various CSV edge cases
Expand All @@ -42,7 +45,7 @@ parse_build_scan_csv() {
idx=0

# shellcheck disable=SC2034 # not all scripts use all of the fetched data
while IFS=, read -r field_1 field_2 field_3 field_4 field_5 field_6 field_7 field_8 field_9 field_10 field_11 field_12 field_13 field_14 field_15 field_16 field_17 field_18 field_19; do
while IFS=, read -r field_1 field_2 field_3 field_4 field_5 field_6 field_7 field_8 field_9 field_10 field_11 field_12 field_13 field_14 field_15 field_16 field_17 field_18 field_19 field_20; do
if [[ "$header_row_read" == "false" ]]; then
header_row_read=true
continue;
Expand Down Expand Up @@ -73,6 +76,11 @@ parse_build_scan_csv() {
executed_not_cacheable_num_tasks[idx]="${field_18}"
executed_not_cacheable_duration[idx]="${field_19}"

# Conditional because build-scan-support-tool does not yet support this field
if [[ -n "$field_20" ]]; then
effective_task_execution_duration[idx]="${field_20}"
fi

((idx++))
done <<< "${build_scan_csv}"
}
57 changes: 54 additions & 3 deletions components/scripts/lib/info.sh
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,42 @@ print_performance_metrics() {
true
}

print_build_caching_leverage_metrics() {
print_performance_characteristics() {
print_performance_characteristics_header

print_realized_build_time_savings

print_build_caching_leverage_metrics

print_executed_cacheable_tasks_warning
}

print_performance_characteristics_header() {
print_bl
info "Build Caching Leverage"
info "----------------------"
info "Performance Characteristics"
info "---------------------------"
}

print_realized_build_time_savings() {
# Do not print realized build time savings at all if these values do not exist
# This can happen since build-scan-support-tool does not yet support these fields
if [[ -n "${effective_task_execution_duration[0]}" && -n "${effective_task_execution_duration[1]}" ]]; then
local value
value=""
# Only calculate realized build time savings when these values are non-zero
# These values can be returned as zero when an error occurs processing the Build Scan data
if [[ "${effective_task_execution_duration[0]}" && "${effective_task_execution_duration[1]}" ]]; then
local first_build second_build realized_savings
first_build=$(format_duration "${effective_task_execution_duration[0]}")
second_build=$(format_duration "${effective_task_execution_duration[1]}")
realized_savings=$(format_duration effective_task_execution_duration[0]-effective_task_execution_duration[1])
value="${realized_savings} wall-clock time (from ${first_build} to ${second_build})"
fi
summary_row "Realized build time savings:" "${value}"
fi
}

print_build_caching_leverage_metrics() {
local task_count_padding
task_count_padding=$(max_length "${avoided_from_cache_num_tasks[1]}" "${executed_cacheable_num_tasks[1]}" "${executed_not_cacheable_num_tasks[1]}")

Expand Down Expand Up @@ -173,7 +204,9 @@ print_build_caching_leverage_metrics() {
value="${taskCount} ${BUILD_TOOL_TASK}s, ${executed_not_cacheable_duration[1]} total execution time"
fi
summary_row "Executed non-cacheable ${BUILD_TOOL_TASK}s:" "${value}"
}

print_executed_cacheable_tasks_warning() {
if (( executed_cacheable_num_tasks[1] > 0)); then
print_bl
warn "Not all cacheable ${BUILD_TOOL_TASK}s' outputs were taken from the build cache in the second build. This reduces the savings in ${BUILD_TOOL_TASK} execution time."
Expand Down Expand Up @@ -230,3 +263,21 @@ create_receipt_file() {
echo "Generated by $(print_version)"
} > "${RECEIPT_FILE}"
}

format_duration() {
local duration=$1
local hours=$((duration/60/60/1000))
local minutes=$((duration/60/1000%60))
local seconds=$((duration/1000%60%60))
local millis=$((duration%1000))

if [[ "${hours}" != 0 ]]; then
printf "%dh " "${hours}"
fi

if [[ "${minutes}" != 0 ]]; then
printf "%dm " "${minutes}"
fi

printf "%d.%03ds" "${seconds}" "${millis}"
}
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ fetch_build_cache_metrics() {

# Overrides info.sh#print_performance_metrics
print_performance_metrics() {
print_build_caching_leverage_metrics
print_performance_characteristics
}

print_quick_links() {
Expand Down Expand Up @@ -314,7 +314,7 @@ two build scans that were published as part of running the experiment. The build
scan of the second build is particularly interesting since this is where you can
inspect what goals were not leveraging the local build cache.

$(explain_build_cache_leverage)
$(explain_performance_characteristics)

The ‘Investigation Quick Links’ section below allows quick navigation to the
most relevant views in build scans to investigate what goals were avoided due to
Expand All @@ -336,7 +336,7 @@ The ‘Summary’ section below captures the configuration of the experiment. No
build scans are available for inspection since publishing was disabled for the
experiment.

$(explain_build_cache_leverage)
$(explain_performance_characteristics)

$(explain_command_to_repeat_experiment)

Expand All @@ -350,12 +350,13 @@ EOF
print_wizard_text "${text}"
}

explain_build_cache_leverage() {
explain_performance_characteristics() {
local text
IFS='' read -r -d '' text <<EOF
The ‘Build Caching Leverage’ section below reveals the realized and potential
savings from build caching. All cacheable goals' outputs need to be taken from
the build cache in the second build for the build to be fully cacheable.
The ‘Performance Characteristics’ section below reveals the realized and
potential savings from build caching. All cacheable goals' outputs need to be
taken from the build cache in the second build for the build to be fully
cacheable.
EOF
echo -n "${text}"
}
Expand Down
Loading