From 5d0f10924b8a98c9ce8804774d413cee02327783 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Thu, 1 Oct 2026 05:40:46 -0500 Subject: [PATCH 1/2] PYTHON-6135 Pin perf benchmarks to uv's optimized managed Python PYTHON-6084 (dda56d3c68) made every uv-invoking step source setup-uv-python.sh, which prefers the toolchain interpreter (UV_PYTHON_PREFERENCE=system). On the performance-benchmarks variant the venv created by the "run server" step was bound to the unoptimized toolchain build (3.10.11 [GCC 11.5.0 Red Hat]) instead of uv's optimized managed build (3.10.11 [Clang 16.0.3]), and the test step reused it, regressing CPU-bound benchmarks by 15-30%. Pin the perf tasks to the managed interpreter in every step that invokes uv: generate_config.py passes task-level UV_PYTHON and UV_PYTHON_PREFERENCE=only-managed to the "run server" and "run tests" functions, setup_tests.py persists that selection in test-env.sh, and setup-uv-python.sh lets a task-level preference win over the toolchain defaults. run-tests.sh re-sources setup-uv-python.sh for direct/local runs. --- .evergreen/generated_configs/functions.yml | 2 ++ .evergreen/generated_configs/tasks.yml | 16 ++++++++++++++++ .evergreen/run-tests.sh | 3 +++ .evergreen/scripts/generate_config.py | 13 +++++++++++-- .evergreen/scripts/setup-uv-python.sh | 11 ++++++----- .evergreen/scripts/setup_tests.py | 11 +++++------ 6 files changed, 43 insertions(+), 13 deletions(-) diff --git a/.evergreen/generated_configs/functions.yml b/.evergreen/generated_configs/functions.yml index e442973c30..df7393de4c 100644 --- a/.evergreen/generated_configs/functions.yml +++ b/.evergreen/generated_configs/functions.yml @@ -102,6 +102,7 @@ functions: - SSL - ORCHESTRATION_FILE - UV_PYTHON + - UV_PYTHON_PREFERENCE - STORAGE_ENGINE - REQUIRE_API_VERSION - DRIVERS_TOOLS @@ -137,6 +138,7 @@ functions: - AWS_SESSION_TOKEN - COVERAGE - UV_PYTHON + - UV_PYTHON_PREFERENCE - LIBMONGOCRYPT_URL - MONGODB_URI - DISABLE_TEST_COMMANDS diff --git a/.evergreen/generated_configs/tasks.yml b/.evergreen/generated_configs/tasks.yml index d4ff6ad5d5..169f8ce85f 100644 --- a/.evergreen/generated_configs/tasks.yml +++ b/.evergreen/generated_configs/tasks.yml @@ -2784,10 +2784,14 @@ tasks: vars: VERSION: v8.0-perf SSL: ssl + UV_PYTHON: 3.10.11 + UV_PYTHON_PREFERENCE: only-managed - func: run tests vars: TEST_NAME: perf SUB_TEST_NAME: sync + UV_PYTHON: 3.10.11 + UV_PYTHON_PREFERENCE: only-managed - func: attach benchmark test results - func: send dashboard data tags: [perf] @@ -2797,10 +2801,14 @@ tasks: vars: VERSION: v8.0-perf SSL: ssl + UV_PYTHON: 3.10.11 + UV_PYTHON_PREFERENCE: only-managed - func: run tests vars: TEST_NAME: perf SUB_TEST_NAME: async + UV_PYTHON: 3.10.11 + UV_PYTHON_PREFERENCE: only-managed - func: attach benchmark test results - func: send dashboard data tags: [perf] @@ -2810,10 +2818,14 @@ tasks: vars: VERSION: v8.0-perf SSL: nossl + UV_PYTHON: 3.10.11 + UV_PYTHON_PREFERENCE: only-managed - func: run tests vars: TEST_NAME: perf SUB_TEST_NAME: sync + UV_PYTHON: 3.10.11 + UV_PYTHON_PREFERENCE: only-managed - func: attach benchmark test results - func: send dashboard data tags: [perf] @@ -2823,10 +2835,14 @@ tasks: vars: VERSION: v8.0-perf SSL: nossl + UV_PYTHON: 3.10.11 + UV_PYTHON_PREFERENCE: only-managed - func: run tests vars: TEST_NAME: perf SUB_TEST_NAME: async + UV_PYTHON: 3.10.11 + UV_PYTHON_PREFERENCE: only-managed - func: attach benchmark test results - func: send dashboard data tags: [perf] diff --git a/.evergreen/run-tests.sh b/.evergreen/run-tests.sh index 358b3e532e..aa1fe97610 100755 --- a/.evergreen/run-tests.sh +++ b/.evergreen/run-tests.sh @@ -26,6 +26,9 @@ else exit 1 fi +# No-op on Evergreen (just.sh already ran this); needed for direct/local runs (PYTHON-6135). +. $SCRIPT_DIR/scripts/setup-uv-python.sh + # Start the test runner. echo "Running tests with UV_PYTHON=${UV_PYTHON:-} UV_PYTHON_SEARCH_PATH=${UV_PYTHON_SEARCH_PATH:-}..." echo "UV_ARGS=${UV_ARGS}" diff --git a/.evergreen/scripts/generate_config.py b/.evergreen/scripts/generate_config.py index 9b4313c423..75d4c59000 100644 --- a/.evergreen/scripts/generate_config.py +++ b/.evergreen/scripts/generate_config.py @@ -1089,12 +1089,19 @@ def create_search_index_tasks(): return [EvgTask(name=task_name, tags=tags, commands=commands)] +# Keep in sync with PERF_PYTHON_VERSION in setup_tests.py. +PERF_PYTHON_VERSION = "3.10.11" + + def create_perf_tasks(): tasks = [] for version, ssl, sync in product(["8.0"], ["ssl", "nossl"], ["sync", "async"]): - vars = dict(VERSION=f"v{version}-perf", SSL=ssl) + # The toolchain build may be this same patch version but is not + # optimized, which regressed CPU-bound benchmarks (PYTHON-6135). + perf_vars = dict(UV_PYTHON=PERF_PYTHON_VERSION, UV_PYTHON_PREFERENCE="only-managed") + vars = dict(VERSION=f"v{version}-perf", SSL=ssl, **perf_vars) server_func = FunctionCall(func="run server", vars=vars) - vars = dict(TEST_NAME="perf", SUB_TEST_NAME=sync) + vars = dict(TEST_NAME="perf", SUB_TEST_NAME=sync, **perf_vars) test_func = FunctionCall(func="run tests", vars=vars) attach_func = FunctionCall(func="attach benchmark test results") send_func = FunctionCall(func="send dashboard data") @@ -1313,6 +1320,7 @@ def create_run_server_func(): "SSL", "ORCHESTRATION_FILE", "UV_PYTHON", + "UV_PYTHON_PREFERENCE", "STORAGE_ENGINE", "REQUIRE_API_VERSION", "DRIVERS_TOOLS", @@ -1342,6 +1350,7 @@ def create_run_tests_func(): "AWS_SESSION_TOKEN", "COVERAGE", "UV_PYTHON", + "UV_PYTHON_PREFERENCE", "LIBMONGOCRYPT_URL", "MONGODB_URI", "DISABLE_TEST_COMMANDS", diff --git a/.evergreen/scripts/setup-uv-python.sh b/.evergreen/scripts/setup-uv-python.sh index 2ebfe04d9d..09397803f5 100755 --- a/.evergreen/scripts/setup-uv-python.sh +++ b/.evergreen/scripts/setup-uv-python.sh @@ -9,6 +9,7 @@ # UV_PYTHON_SEARCH_PATH - the Python toolchain bin dir for the request, so uv # uses the toolchain Python instead of downloading one. # UV_PYTHON_PREFERENCE - "system" so the toolchain wins over managed installs. +# A preference set by the task is left alone. # UV_PYTHON - the Python interpreter uv uses; defaults to CPython # 3.10 when the task does not set one. set -euo pipefail @@ -85,11 +86,11 @@ elif _dir=$(_toolchain_dir "$UV_PYTHON"); then _search_path="$_dir" fi -# Point uv at the toolchain Python when there is one. On CI the toolchain dir -# is already first on PATH (configure-env.sh), so this mainly benefits local -# hosts and later steps, keeping `uv sync` and `uv tool install` on the -# toolchain interpreter instead of downloading a managed one. -if [ -n "$_search_path" ]; then +# Point uv at the toolchain Python when there is one and the task did not set +# its own preference: a task-level UV_PYTHON_PREFERENCE wins (PYTHON-6135). +# On CI the toolchain dir is already first on PATH (configure-env.sh), so this +# mainly benefits local hosts and later steps. +if [ -n "$_search_path" ] && [ -z "${UV_PYTHON_PREFERENCE:-}" ]; then export UV_PYTHON_SEARCH_PATH="$_search_path" export UV_PYTHON_PREFERENCE="system" fi diff --git a/.evergreen/scripts/setup_tests.py b/.evergreen/scripts/setup_tests.py index b57188eee1..172cbe1678 100644 --- a/.evergreen/scripts/setup_tests.py +++ b/.evergreen/scripts/setup_tests.py @@ -51,7 +51,7 @@ # Map the test name to test group. GROUP_MAP = dict(mockupdb="mockupdb", perf="perf") -# The python version used for perf tests. +# Keep in sync with PERF_PYTHON_VERSION in generate_config.py. PERF_PYTHON_VERSION = "3.10.11" # The libmongocrypt release used when LIBMONGOCRYPT_URL is not set. Must be at @@ -515,13 +515,12 @@ def handle_test_env() -> None: run_command("tar xf single_and_multi_document.tgz", cwd=data_dir) write_env("TEST_PATH", str(data_dir)) write_env("OUTPUT_FILE", str(ROOT / "results.json")) - # Overwrite the UV_PYTHON value from env.sh, and unset the toolchain - # search-path variables: an empty value would make uv reject the request, - # and a toolchain path would miss the exact patch version requested. - write_env("UV_PYTHON", "") + # The toolchain build may be this same patch version but is not + # optimized, which regressed CPU-bound benchmarks (PYTHON-6135). + write_env("UV_PYTHON", PERF_PYTHON_VERSION) + write_env("UV_PYTHON_PREFERENCE", "only-managed") with ENV_FILE.open("a", newline="\n") as fid: fid.write("unset UV_PYTHON_SEARCH_PATH\n") - fid.write("unset UV_PYTHON_PREFERENCE\n") UV_ARGS.append(f"--python={PERF_PYTHON_VERSION}") From 56b19151a202956ba70ef9b12ec1e75c5077f9b4 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Thu, 1 Oct 2026 19:53:38 -0500 Subject: [PATCH 2/2] PYTHON-6135 Move PERF_PYTHON_VERSION to utils.py --- .evergreen/scripts/generate_config.py | 5 +---- .evergreen/scripts/setup_tests.py | 4 +--- .evergreen/scripts/utils.py | 3 +++ 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/.evergreen/scripts/generate_config.py b/.evergreen/scripts/generate_config.py index 75d4c59000..9ec13d5037 100644 --- a/.evergreen/scripts/generate_config.py +++ b/.evergreen/scripts/generate_config.py @@ -43,6 +43,7 @@ git_get_project, ) from shrub.v3.evg_task import EvgTask, EvgTaskDependency, EvgTaskRef +from utils import PERF_PYTHON_VERSION ############## # Variants @@ -1089,10 +1090,6 @@ def create_search_index_tasks(): return [EvgTask(name=task_name, tags=tags, commands=commands)] -# Keep in sync with PERF_PYTHON_VERSION in setup_tests.py. -PERF_PYTHON_VERSION = "3.10.11" - - def create_perf_tasks(): tasks = [] for version, ssl, sync in product(["8.0"], ["ssl", "nossl"], ["sync", "async"]): diff --git a/.evergreen/scripts/setup_tests.py b/.evergreen/scripts/setup_tests.py index 172cbe1678..6c77ecabf9 100644 --- a/.evergreen/scripts/setup_tests.py +++ b/.evergreen/scripts/setup_tests.py @@ -13,6 +13,7 @@ ENV_FILE, HERE, LOGGER, + PERF_PYTHON_VERSION, PLATFORM, ROOT, TEST_SUITE_MAP, @@ -51,9 +52,6 @@ # Map the test name to test group. GROUP_MAP = dict(mockupdb="mockupdb", perf="perf") -# Keep in sync with PERF_PYTHON_VERSION in generate_config.py. -PERF_PYTHON_VERSION = "3.10.11" - # The libmongocrypt release used when LIBMONGOCRYPT_URL is not set. Must be at # least 1.20.0 for the GA "substring" query type. LIBMONGOCRYPT_VERSION = "1.20.2" diff --git a/.evergreen/scripts/utils.py b/.evergreen/scripts/utils.py index 3f948dd292..75d4fc89b3 100644 --- a/.evergreen/scripts/utils.py +++ b/.evergreen/scripts/utils.py @@ -81,6 +81,9 @@ class Distro: EXTRA_TESTS = ["aws_lambda", "doctest"] +# The managed Python version used for perf tests (PYTHON-6135). +PERF_PYTHON_VERSION = "3.10.11" + # Tests that do not use run-mongodb directly. NO_RUN_ORCHESTRATION = [ "auth_oidc",