diff --git a/.github/workflows/codspeed.yml b/.github/workflows/codspeed.yml index 39cd8eb261..427262d598 100644 --- a/.github/workflows/codspeed.yml +++ b/.github/workflows/codspeed.yml @@ -33,6 +33,8 @@ jobs: version: '1.16.5' - name: Run the benchmarks uses: CodSpeedHQ/action@f99becdce5e5d51fd556489ebef684f4ecfd6286 # v4.18.5 + env: + ZARR_BENCHMARK_CLEAR_CACHE: '1' with: mode: walltime run: hatch run test.py3.12-minimal:pytest tests/benchmarks --codspeed diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ab78cfbe2b..ce6b7e3eba 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -178,6 +178,8 @@ jobs: - name: Install Hatch run: python -m pip install hatch==1.16.5 - name: Run Benchmarks + env: + ZARR_BENCHMARK_CLEAR_CACHE: '1' run: | hatch env run --env "test.py3.13-minimal" run-benchmark diff --git a/changes/4199.bugfix.md b/changes/4199.bugfix.md new file mode 100644 index 0000000000..d0c522cd7e --- /dev/null +++ b/changes/4199.bugfix.md @@ -0,0 +1 @@ +The end-to-end benchmarks no longer invoke `sudo` to drop the OS page cache during a regular `pytest` run. Cache clearing is now opt-in via the `ZARR_BENCHMARK_CLEAR_CACHE` environment variable, which the benchmark CI jobs set. diff --git a/tests/benchmarks/test_e2e.py b/tests/benchmarks/test_e2e.py index 487485e262..de69fca59b 100644 --- a/tests/benchmarks/test_e2e.py +++ b/tests/benchmarks/test_e2e.py @@ -4,8 +4,10 @@ from __future__ import annotations +import os import platform import subprocess +import warnings from functools import lru_cache from operator import getitem, setitem from typing import TYPE_CHECKING, Any, Literal @@ -21,12 +23,27 @@ def clear_cache() -> None: + """Drop the OS page cache between benchmark rounds. + + Requires passwordless sudo, so it is opt-in: set `ZARR_BENCHMARK_CLEAR_CACHE=1` + to enable it (as the benchmark CI jobs do). By default this is a no-op, so a + plain `pytest` run never prompts for a sudo password (see issue #4199). + `sudo -n` guarantees we fail instead of blocking on a password prompt even + when the variable is set. + """ + if os.environ.get("ZARR_BENCHMARK_CLEAR_CACHE", "") not in ("1", "true"): + return if platform.system() == "Darwin": - subprocess.call(["sync", "&&", "sudo", "purge"]) + subprocess.call(["sync"]) + subprocess.call(["sudo", "-n", "purge"]) elif platform.system() == "Linux": - subprocess.call(["sudo", "sh", "-c", "sync; echo 3 > /proc/sys/vm/drop_caches"]) + subprocess.call(["sudo", "-n", "sh", "-c", "sync; echo 3 > /proc/sys/vm/drop_caches"]) else: - raise Exception("Unsupported platform") # noqa: TRY002 + warnings.warn( + f"ZARR_BENCHMARK_CLEAR_CACHE is set but cache clearing is not supported on " + f"{platform.system()}; skipping.", + stacklevel=2, + ) if TYPE_CHECKING: