From 901c452c82bdee152b4499a4e7b7f3bfcfa03c21 Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Wed, 20 May 2026 13:59:46 +0000 Subject: [PATCH] test.py: reduce cgroup overhead in resource metrics gathering Only enable the memory controller in cgroup subtree_control instead of all available controllers. cpu.stat is available in cgroup v2 without enabling the cpu controller (base accounting), and enabling io/pids/cpu controllers adds unnecessary per-operation kernel overhead to Scylla processes - particularly the memory controller's per-page-cache-operation accounting combined with io controller overhead during heavy I/O. Additionally, restrict SystemResourceMonitor to the master process only. System-wide metrics (CPU%, memory) are identical from any process, so running a monitoring thread in each xdist worker was redundant and added unnecessary SQLite write contention and thread scheduling noise. Co-Authored-By: Claude Opus 4.6 (200K context) --- test/pylib/resource_gather.py | 17 ++++++++++------- test/pylib/runner.py | 7 +++++-- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/test/pylib/resource_gather.py b/test/pylib/resource_gather.py index 81fc92adc9..2865dd85ac 100644 --- a/test/pylib/resource_gather.py +++ b/test/pylib/resource_gather.py @@ -279,13 +279,16 @@ def _is_cgroup_rw() -> bool: return False def propagate_subtree_controls(group: Path): - with open(group / 'cgroup.controllers', 'r') as f: - controllers = f.readline().strip() - if not controllers: - return - controllers = " ".join(map(lambda x: f"+{x}", controllers.split(" "))) - with open(group / 'cgroup.subtree_control', 'w') as f: - f.write(controllers) + # Only enable the memory controller. cpu.stat is available without + # enabling the cpu controller (it's base cgroup v2 accounting). + # Enabling all controllers (cpu, io, pids, etc.) adds unnecessary + # per-operation kernel overhead to child processes - in particular, + # the io controller adds accounting to every I/O operation. + with open(group / "cgroup.controllers", "r") as f: + if "memory" not in f.readline().split(): + return + with open(group / "cgroup.subtree_control", "w") as f: + f.write("+memory") def setup_cgroup(is_required: bool) -> None: diff --git a/test/pylib/runner.py b/test/pylib/runner.py index e139e6c6d2..688fd66b8a 100644 --- a/test/pylib/runner.py +++ b/test/pylib/runner.py @@ -304,8 +304,11 @@ def pytest_sessionstart(session: pytest.Session) -> None: if not is_xdist_worker and SCYLLA_TEST_CGROUP_BASE_ENV not in os.environ: setup_cgroup(is_required=True) setup_worker_cgroup() - _system_resource_monitor = SystemResourceMonitor(temp_dir) - _system_resource_monitor.start() + # System-wide resource metrics (CPU%, memory) are identical from any process. + # Only the master needs to record them. + if not is_xdist_worker: + _system_resource_monitor = SystemResourceMonitor(temp_dir) + _system_resource_monitor.start()