Skip to content
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

test: modify benchmarking workflow and publish build performance artifact #4354

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 11 additions & 5 deletions .pipelines/templates/.builder-release-template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ steps:
- bash: |
pwd
ls -R
displayName: show Directory
displayName: Show Directory
- bash: |
set -x
GOPATH="$(go env GOPATH)"
Expand All @@ -49,7 +49,7 @@ steps:
GO111MODULE=on go install cuelang.org/go/cmd/cue@latest
popd
cue export ./schemas/manifest.cue > ./parts/linux/cloud-init/artifacts/manifest.json
displayName: setup cue
displayName: Setup Cue
- bash: |
SKU_NAME=${OS_VERSION} && \
if [[ "${HYPERV_GENERATION,,}" == "v2" ]]; then SKU_NAME="${SKU_NAME}gen2"; fi && \
Expand Down Expand Up @@ -107,7 +107,7 @@ steps:
-e LINUX_MSI_RESOURCE_ID=${AZURE_MSI_RESOURCE_ID} \
${CONTAINER_IMAGE} make -f packer.mk run-packer
retryCountOnTaskFailure: 3
displayName: Building VHD
displayName: Build VHD
- script: |
OS_DISK_URI="$(cat packer-output | grep "OSDiskUri:" | cut -d " " -f 2)" && \
MANAGED_SIG_ID="$(cat packer-output | grep "ManagedImageSharedImageGalleryId:" | cut -d " " -f 2)" && \
Expand Down Expand Up @@ -144,13 +144,19 @@ steps:
inputs:
artifactName: 'vhd-release-notes-${{ parameters.artifactName }}'
targetPath: 'release-notes.txt'
displayName: publish release notes
displayName: Publish Release Notes
- task: PublishPipelineArtifact@0
inputs:
artifactName: 'vhd-image-bom-${{ parameters.artifactName }}'
targetPath: 'image-bom.json'
displayName: publish container image list
condition: and(succeeded(), eq(variables.DRY_RUN, 'False'))
- task: PublishPipelineArtifact@1
inputs:
artifactName: 'build-performance-data-${{ parameters.artifactName }}'
targetPath: 'vhd-build-performance-data.json'
displayName: Publish Build Performance Data
condition: succeeded()
- bash: |
echo MODE=$(MODE) && \
PKR_RG_NAME="$(cat packer-output | grep "ResourceGroupName" | cut -d "'" -f 2 | head -1)" && \
Expand Down Expand Up @@ -234,7 +240,7 @@ steps:
-e ARCHITECTURE=${ARCHITECTURE} \
-e IMAGE_VERSION=${IMAGE_VERSION} \
${CONTAINER_IMAGE} make -f packer.mk generate-sas
displayName: Getting Shared Access Signature URI
displayName: Get Shared Access Signature URI
condition: and(succeeded(), eq(variables.DRY_RUN, 'False'))
- task: PublishPipelineArtifact@1
inputs:
Expand Down
84 changes: 62 additions & 22 deletions parts/linux/cloud-init/artifacts/cse_helpers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -379,40 +379,80 @@ should_skip_nvidia_drivers() {
echo "$should_skip"
}

start_watch () {
capture_time=$(date +%s)
start_timestamp=$(date +%H:%M:%S)
installJq () {
# jq is not available until downloaded in install-dependencies.sh with the installDeps function
# but it is needed earlier to call the capture_benchmarks function in pre-install-dependencies.sh
output=$(jq --version)
if [ -n "$output" ]; then
echo "$output"
else
if [[ "${OS}" == "MARINER" ]]; then
sudo tdnf install -y jq
echo "jq was installed: $(jq --version)"
else
apt_get_install 5 1 60 jq
echo "jq was installed: $(jq --version)"
fi
fi
}

stop_watch () {
capture_benchmarks () {
# the capture_benchmarks function is used to capture benchmark data for each section in VHD build scripts
# data will be stored in a JSON file and published as an artifact to be evaluated by github actions
set +x

local is_final_section=$1
local title=$2

local current_time=$(date +%s)
local end_timestamp=$(date +%H:%M:%S)
local difference_in_seconds=$((current_time - ${1}))
if [ "$is_final_section" = true ]; then
local difference_in_seconds=$((current_time - script_start_stopwatch))
else
local difference_in_seconds=$((current_time - section_start_stopwatch))
fi

local elapsed_hours=$(($difference_in_seconds/3600))
local elapsed_minutes=$((($difference_in_seconds%3600)/60))
local elapsed_seconds=$(($difference_in_seconds%60))
printf -v total_time_elapsed "%02d:%02d:%02d" $elapsed_hours $elapsed_minutes $elapsed_seconds

# if the final section of the current script has not yet been reached, store the latest recorded benchmarking data in an array
if [[ ! "$is_final_section" == true ]]; then
benchmarks+=($title)
benchmarks+=($section_start_timestamp)
benchmarks+=($end_timestamp)
benchmarks+=($total_time_elapsed)
fi

printf -v benchmark "'${2}' - Total Time Elapsed: %02d:%02d:%02d" $elapsed_hours $elapsed_minutes $elapsed_seconds
if [ ${3} == true ]; then
printf -v start " Start time: $script_start_timestamp"
else
printf -v start " Start time: $start_timestamp"
if [[ "$is_final_section" == true ]]; then

# if current section is the final section of the current script, create a JSON object for the script as a whole
script_object=$(jq -n --arg script_name "$title" --arg script_start_timestamp "$script_start_timestamp" --arg end_timestamp "$end_timestamp" --arg total_time_elapsed "$total_time_elapsed" '{($script_name): {"overall": {"start_time": $script_start_timestamp, "end_time": $end_timestamp, "total_time_elapsed": $total_time_elapsed}}}')

#iterate over the benchmarks array in order to retrieve data from previous sections and create section objects for each
for ((i=0; i<${#benchmarks[@]}; i+=4)); do

section_object=$(jq -n --arg section_name "${benchmarks[i]}" --arg section_start_timestamp "${benchmarks[i+1]}" --arg end_timestamp "${benchmarks[i+2]}" --arg total_time_elapsed "${benchmarks[i+3]}" '{($section_name): {"start_time": $section_start_timestamp, "end_time": $end_timestamp, "total_time_elapsed": $total_time_elapsed}}')

# append the section objects to the current script object
script_object=$(jq -n --argjson script_object "$script_object" --argjson section_object "$section_object" --arg script_name "$title" '$script_object | .[$script_name] += $section_object')

done

echo "Benchmarks:"
echo "$script_object" | jq -C .

# after all section objects are appended to the current script object, append current script object to the array in ${VHD_BUILD_PERF_DATA}
jq ". += [$script_object]" ${VHD_BUILD_PERF_DATA} > tmp.json && mv tmp.json ${VHD_BUILD_PERF_DATA}
chmod 755 ${VHD_BUILD_PERF_DATA}
fi
printf -v end " End Time: $end_timestamp"
echo -e "\n$benchmark\n"
benchmarks+=("$benchmark")
benchmarks+=("$start")
benchmarks+=("$end")
}

show_benchmarks () {
echo -e "\nBenchmarks:\n"
for i in "${benchmarks[@]}"; do
echo " $i"
done
echo
# reset timers for next section
section_start_stopwatch=$(date +%s)
section_start_timestamp=$(date +%H:%M:%S)

set -x
}

#HELPERSEOF
2 changes: 1 addition & 1 deletion pkg/agent/testdata/AKSUbuntu1604+Containerd/CustomData
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ write_files:
encoding: gzip
owner: root
content: !!binary |
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



Expand Down
Loading
Loading