From e761153cff6761a3a06c1878c7b6b1107365277c Mon Sep 17 00:00:00 2001 From: Fu Hanxi Date: Sat, 29 Jan 2022 14:38:56 +0800 Subject: [PATCH] ci: adjust parallel count based on build item count --- .gitlab/ci/build.yml | 11 ++-- .gitlab/ci/pre_check.yml | 7 ++- .../python_packages/ttfw_idf/CIScanTests.py | 57 ++++++++++++++++--- 3 files changed, 57 insertions(+), 18 deletions(-) diff --git a/.gitlab/ci/build.yml b/.gitlab/ci/build.yml index 60d5544376..af1d3f455e 100644 --- a/.gitlab/ci/build.yml +++ b/.gitlab/ci/build.yml @@ -291,7 +291,7 @@ build_examples_cmake_esp32: extends: - .build_examples_cmake_template - .rules:build:example_test-esp32 - parallel: 10 + parallel: 12 variables: IDF_TARGET: esp32 @@ -339,7 +339,7 @@ build_test_apps_esp32: extends: - .build_test_apps_template - .rules:build:custom_test-esp32 - parallel: 8 + parallel: 2 variables: IDF_TARGET: esp32 @@ -347,7 +347,7 @@ build_test_apps_esp32s2: extends: - .build_test_apps_template - .rules:build:custom_test-esp32s2 - parallel: 8 + parallel: 2 variables: IDF_TARGET: esp32s2 @@ -355,7 +355,7 @@ build_test_apps_esp32s3: extends: - .build_test_apps_template - .rules:build:custom_test-esp32s3 - parallel: 8 + parallel: 2 variables: IDF_TARGET: esp32s3 @@ -363,7 +363,7 @@ build_test_apps_esp32c3: extends: - .build_test_apps_template - .rules:build:custom_test-esp32c3 - parallel: 8 + parallel: 2 variables: IDF_TARGET: esp32c3 @@ -371,7 +371,6 @@ build_test_apps_esp32c2: extends: - .build_test_apps_template - .rules:build:custom_test-esp32c2 - parallel: 8 variables: IDF_TARGET: esp32c2 diff --git a/.gitlab/ci/pre_check.yml b/.gitlab/ci/pre_check.yml index abab8b035f..aa69df9abe 100644 --- a/.gitlab/ci/pre_check.yml +++ b/.gitlab/ci/pre_check.yml @@ -163,11 +163,12 @@ scan_tests: examples/bluetooth/esp_ble_mesh/ble_mesh_console examples/bluetooth/hci/controller_hci_uart_esp32 examples/wifi/iperf + EXTRA_EVALUATE_ARGS: '--evaluate-parallel-count --config "sdkconfig.ci=default" --config "sdkconfig.ci.*=" --config "=default"' script: - - run_cmd python $CI_SCAN_TESTS_PY example_test $EXAMPLE_TEST_DIR -b cmake --exclude examples/build_system/idf_as_lib -c $CI_TARGET_TEST_CONFIG_FILE -o $EXAMPLE_TEST_OUTPUT_DIR --extra_test_dirs $EXTRA_TEST_DIRS - - run_cmd python $CI_SCAN_TESTS_PY test_apps $TEST_APPS_TEST_DIR -c $CI_TARGET_TEST_CONFIG_FILE -o $TEST_APPS_OUTPUT_DIR + - run_cmd python $CI_SCAN_TESTS_PY example_test $EXAMPLE_TEST_DIR -b cmake --exclude examples/build_system/idf_as_lib -c $CI_TARGET_TEST_CONFIG_FILE -o $EXAMPLE_TEST_OUTPUT_DIR --extra_test_dirs $EXTRA_TEST_DIRS $EXTRA_EVALUATE_ARGS + - run_cmd python $CI_SCAN_TESTS_PY test_apps $TEST_APPS_TEST_DIR -c $CI_TARGET_TEST_CONFIG_FILE -o $TEST_APPS_OUTPUT_DIR $EXTRA_EVALUATE_ARGS - set_component_ut_vars - - run_cmd python $CI_SCAN_TESTS_PY component_ut $COMPONENT_UT_DIRS --exclude $COMPONENT_UT_EXCLUDES -c $CI_TARGET_TEST_CONFIG_FILE -o $COMPONENT_UT_OUTPUT_DIR --combine-all-targets --except-targets linux + - run_cmd python $CI_SCAN_TESTS_PY component_ut $COMPONENT_UT_DIRS --exclude $COMPONENT_UT_EXCLUDES -c $CI_TARGET_TEST_CONFIG_FILE -o $COMPONENT_UT_OUTPUT_DIR --combine-all-targets --except-targets linux $EXTRA_EVALUATE_ARGS # For release tag pipelines only, make sure the tag was created with 'git tag -a' so it will update # the version returned by 'git describe' diff --git a/tools/ci/python_packages/ttfw_idf/CIScanTests.py b/tools/ci/python_packages/ttfw_idf/CIScanTests.py index 20ed6655c0..729ac24919 100644 --- a/tools/ci/python_packages/ttfw_idf/CIScanTests.py +++ b/tools/ci/python_packages/ttfw_idf/CIScanTests.py @@ -8,8 +8,8 @@ from copy import deepcopy from typing import Any from ci.idf_ci_utils import get_pytest_app_paths -from find_apps import find_apps -from find_build_apps import BUILD_SYSTEM_CMAKE, BUILD_SYSTEMS +from find_apps import find_apps, find_builds_for_app +from find_build_apps import BUILD_SYSTEM_CMAKE, BUILD_SYSTEMS, config_rules_from_str from idf_py_actions.constants import PREVIEW_TARGETS, SUPPORTED_TARGETS from ttfw_idf.IDFAssignTest import ExampleAssignTest, TestAppsAssignTest @@ -29,6 +29,8 @@ BUILD_ALL_LABELS = [ 'BOT_LABEL_WEEKEND_TEST', ] +BUILD_PER_JOB = 30 # each build takes 1 mins around + def _has_build_all_label(): # type: () -> bool for label in BUILD_ALL_LABELS: @@ -101,6 +103,19 @@ def main(): # type: () -> None help='add this flag to combine all target jsons into one') parser.add_argument('--except-targets', nargs='+', help='only useful when "--combine-all-targets". Specified targets would be skipped.') + parser.add_argument( + '--config', + action='append', + help='Only useful when "--evaluate-parallel-count" is flagged.' + 'Adds configurations (sdkconfig file names) to build. This can either be ' + + 'FILENAME[=NAME] or FILEPATTERN. FILENAME is the name of the sdkconfig file, ' + + 'relative to the project directory, to be used. Optional NAME can be specified, ' + + 'which can be used as a name of this configuration. FILEPATTERN is the name of ' + + 'the sdkconfig file, relative to the project directory, with at most one wildcard. ' + + 'The part captured by the wildcard is used as the name of the configuration.', + ) + parser.add_argument('--evaluate-parallel-count', action='store_true', + help='suggest parallel count according to build items') args = parser.parse_args() build_test_case_apps, build_standalone_apps = _judge_build_or_not(args.test_type, args.build_all) @@ -175,6 +190,7 @@ def main(): # type: () -> None scan_info_dict[target]['standalone_apps'] = set() test_case_apps_preserve_default = True if build_system == 'cmake' else False output_files = [] + build_items_total_count = 0 for target in SUPPORTED_TARGETS: # get pytest apps paths pytest_app_paths = set() @@ -204,15 +220,35 @@ def main(): # type: () -> None }) output_path = os.path.join(args.output_path, 'scan_{}_{}.json'.format(target.lower(), build_system)) with open(output_path, 'w') as fw: + if args.evaluate_parallel_count: + build_items = [] + config_rules = config_rules_from_str(args.config or []) + for app in apps: + build_items += find_builds_for_app( + app['app_dir'], + app['app_dir'], + 'build', + '', + app['target'], + app['build_system'], + config_rules, + app['preserve'], + ) + print('Found {} builds'.format(len(build_items))) + if args.combine_all_targets: + if (args.except_targets and target not in [t.lower() for t in args.except_targets]) \ + or (not args.except_targets): + build_items_total_count += len(build_items) + else: + print(f'suggest set parallel count for target {target} to {len(build_items) // BUILD_PER_JOB + 1}') fw.writelines([json.dumps(app) + '\n' for app in apps]) - if args.combine_all_targets: - if (args.except_targets and target not in [t.lower() for t in args.except_targets]) \ - or (not args.except_targets): - output_files.append(output_path) - build_items_total_count += len(build_items) - else: - print(f'skipping combining target {target}') + if args.combine_all_targets: + if (args.except_targets and target not in [t.lower() for t in args.except_targets]) \ + or (not args.except_targets): + output_files.append(output_path) + else: + print(f'skipping combining target {target}') if args.combine_all_targets: scan_all_json = os.path.join(args.output_path, f'scan_all_{build_system}.json') @@ -224,6 +260,9 @@ def main(): # type: () -> None fw.writelines(lines) print(f'combined into file: {scan_all_json}') + if args.evaluate_parallel_count: + print(f'Total build: {build_items_total_count}. Suggest set parallel count for all target to {build_items_total_count // BUILD_PER_JOB + 1}') + if __name__ == '__main__': main()