Merge "STT: Generate output result from the test builds" am: a5b9424827 am: f901f0a00d

Original change: https://android-review.googlesource.com/c/platform/development/+/2623792

Change-Id: Iabe14f1ad729293cff66dc755899938ed8d39093
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Justin Yun
2023-06-14 01:24:16 +00:00
committed by Automerger Merge Worker
2 changed files with 147 additions and 31 deletions

106
treble/combined_build_test.sh Normal file → Executable file
View File

@@ -15,15 +15,17 @@
# limitations under the License.
usage() {
echo "usage: "$0" -t TARGET -v VARIANT [-d DIST_OUT] [-a ALTER_TARGET] [-c] [GOALS ...]"
echo "usage: ${0} -t TARGET -v VARIANT [-d DIST_OUT] [-a ALTER_TARGET] [-c] [-o] [-r] [GOALS ...]"
echo " -t TARGET : Primay target to build"
echo " -v VARIANT : Build variant (ex. user, userdebug)"
echo " -d DIST_OUT : Path for dist out"
echo " -a ALTER_TARGET: The secondary target that shares the build artifacts with the primary target"
echo " -c : Installclean between each build"
echo " -c : Run the target build again after installclean for reference"
echo ' -o : Write build time results to "build_time_results.txt" file in "${OUT_DIR}" or "${DIST_OUT}/logs" if -d defined'
echo " -r : Dryrun to see the commands without actually building the targets"
}
while getopts ha:cd:t:v: opt; do
while getopts ha:cd:ort:v: opt; do
case "${opt}" in
h)
usage
@@ -32,11 +34,17 @@ while getopts ha:cd:t:v: opt; do
alter_target="${OPTARG}"
;;
c)
installclean=true
installclean="true"
;;
d)
dist_dir="${OPTARG}"
;;
o)
result_out="build_time_results.txt"
;;
r)
dry_run="true"
;;
t)
target="${OPTARG}"
;;
@@ -49,48 +57,84 @@ while getopts ha:cd:t:v: opt; do
esac
done
if [[ -z ${target} ]]; then
if [[ -z "${target}" ]]; then
echo "-t must set for the primary target"
usage
exit 1
fi
if [[ -z ${variant} ]]; then
if [[ -z "${variant}" ]]; then
echo "-v must set for build variant"
usage
exit 1
fi
goals="${@:OPTIND}"
readonly ANDROID_TOP="$(cd $(dirname $0)/../..; pwd)"
cd "${ANDROID_TOP}"
out_dir="${OUT_DIR:-out}"
if [[ -n "${dist_dir}" ]]; then
out_dir="${dist_dir}/logs"
fi
base_command="build/soong/soong_ui.bash --make-mode"
if [[ ! -z ${dist_dir} ]]; then
if [[ -n "${dist_dir}" ]]; then
base_command="${base_command} DIST_DIR=${dist_dir} dist"
fi
run_command() {
if [[ -z "${dry_run}" ]]; then
$1
else
echo "$1"
fi
}
write_output() {
if [[ -z "${result_out}" || -n "${dry_run}" ]]; then
echo "Output: $1"
else
echo "$1" >> "${out_dir}/${result_out}"
fi
}
get_build_trace() {
run_command "cp -f ${out_dir}/build.trace.gz ${out_dir}/${1}"
if [[ -n "${result_out}" ]]; then
write_output "$(python3 development/treble/read_build_trace_gz.py ${out_dir}/${1})"
fi
}
if [[ -n "${result_out}" ]]; then
run_command "rm -f ${out_dir}/${result_out}"
write_output "target, soong, kati, ninja, total"
fi
# Build the target first.
echo "Initial build..."
${base_command} TARGET_PRODUCT=${target} TARGET_BUILD_VARIANT=${variant} ${goals}
run_command "${base_command} TARGET_PRODUCT=${target} TARGET_BUILD_VARIANT=${variant} ${goals}"
if [[ ! -z ${alter_target} ]]; then
# Building two targets with a single artifacts
if [[ ! -z ${installclean} ]]; then
echo "Installclean for the alternative target..."
${base_command} TARGET_PRODUCT=${alter_target} TARGET_BUILD_VARIANT=${variant} installclean
fi
echo "Build the alternative target..."
${base_command} TARGET_PRODUCT=${alter_target} TARGET_BUILD_VARIANT=${variant} ${goals}
if [[ ! -z ${installclean} ]]; then
echo "Installclean for the primary target..."
${base_command} TARGET_PRODUCT=${target} TARGET_BUILD_VARIANT=${variant} installclean
fi
echo "Build the primary target again..."
${base_command} TARGET_PRODUCT=${target} TARGET_BUILD_VARIANT=${variant} ${goals}
else
# Build again just after installclean for reference
if [[ ! -z ${installclean} ]]; then
echo "Installclean..."
${base_command} TARGET_PRODUCT=${target} TARGET_BUILD_VARIANT=${variant} installclean
fi
echo "Build the target again..."
${base_command} TARGET_PRODUCT=${target} TARGET_BUILD_VARIANT=${variant} ${goals}
if [[ -n "${installclean}" ]]; then
# Run the same build after installclean
echo "Installclean..."
run_command "${base_command} TARGET_PRODUCT=${target} TARGET_BUILD_VARIANT=${variant} installclean"
echo "Build the same initial build..."
run_command "${base_command} TARGET_PRODUCT=${target} TARGET_BUILD_VARIANT=${variant} ${goals}"
get_build_trace "build_${target}_installclean.trace.gz"
fi
if [[ -n "${alter_target}" ]]; then
# Building two targets with a single artifacts
echo "Installclean for the alternative target..."
run_command "${base_command} TARGET_PRODUCT=${alter_target} TARGET_BUILD_VARIANT=${variant} installclean"
echo "Build the alternative target..."
run_command "${base_command} TARGET_PRODUCT=${alter_target} TARGET_BUILD_VARIANT=${variant} ${goals}"
get_build_trace "build_${alter_target}_ab.trace.gz"
echo "Installclean for the primary target..."
run_command "${base_command} TARGET_PRODUCT=${target} TARGET_BUILD_VARIANT=${variant} installclean"
echo "Build the primary target again..."
run_command "${base_command} TARGET_PRODUCT=${target} TARGET_BUILD_VARIANT=${variant} ${goals}"
get_build_trace "build_${target}_aba.trace.gz"
fi

View File

@@ -0,0 +1,72 @@
#!/usr/bin/env python3
#
# Copyright (C) 2023 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import gzip
import json
import os
import sys
from collections import defaultdict
READ_DURATION = [
'soong',
'kati build',
'ninja',
'total',
]
class Trace:
def __init__(self, trace_file):
self.duration = dict()
self._queue = defaultdict(list)
self.target = os.path.splitext(os.path.basename(trace_file))[0]
if not os.path.isfile(trace_file):
return
self._trace_file = gzip.open(trace_file, 'r')
self._trace_data = json.load(self._trace_file)
for t in self._trace_data:
if 'ph' not in t:
continue
if t['ph'] == 'X':
self.duration[t['name']] = t['dur']
continue
if t['ph'] == 'B':
self._queue[(t['pid'], t['pid'])].append((t['name'], t['ts']))
continue
if t['ph'] == 'E':
queue = self._queue[(t['pid'], t['pid'])]
if not queue:
raise Exception('pid:{}, tid:{} not started'.format(t['pid'], t['pid']))
name, ts = queue.pop()
self.duration[name] = t['ts'] - ts
continue
def out_durations(self):
out_str = self.target
for name in READ_DURATION:
if name not in self.duration:
continue
out_str = '{}, {}'.format(out_str, self.duration[name])
out_str += '\n'
sys.stdout.write(out_str)
def main(argv):
trace = Trace(argv[1])
trace.out_durations()
if __name__ == '__main__':
main(sys.argv)