[PATCH 2/8] rteval: Don't create measurement cpuset with --onlyload
COOLING12d
From: John Kacur <jkacur@redhat.com>
Date: 2026-09-22 22:26:35
Subsystem:
the rest · Maintainer:
Linus Torvalds
--onlyload runs the loads but no measurement threads, yet CpusetManager always created the rteval_measurement cpuset as an isolated partition. Nothing is ever migrated into it in this mode, so it served only to remove its CPUs from the root cgroup where the taskset-bound loads run, leaving those loads with fewer (or no) usable CPUs for no benefit. Add a create_measurement parameter to CpusetManager (default True) and skip creating the measurement cpuset when it is False. rteval-cmd passes create_measurement=not onlyload, so --onlyload now runs loads without an empty isolated measurement partition getting in their way. Add a unit test asserting the measurement cpuset is not created when create_measurement is False. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: John Kacur <jkacur@redhat.com> --- rteval-cmd | 3 ++- rteval/cpusetmanager.py | 22 ++++++++++++++-------- tests/test_cpusetmanager.py | 18 ++++++++++++++++++ 3 files changed, 34 insertions(+), 9 deletions(-)
diff --git a/rteval-cmd b/rteval-cmd
index 438ead95f843..7a8512e1a254 100755
--- a/rteval-cmd
+++ b/rteval-cmd@@ -572,7 +572,8 @@ if __name__ == '__main__': housekeeping_cpus=housekeeping_cpus, measurement_cpus=msrcfg_cpus, logger=logger, - housekeeping_isolated=rtevcfg.housekeeping_isolated + housekeeping_isolated=rtevcfg.housekeeping_isolated, + create_measurement=not rtevcfg.onlyload ) # Pass cpuset_manager to RtEval (None if not using cpusets)
diff --git a/rteval/cpusetmanager.py b/rteval/cpusetmanager.py
index a204312eda9a..8b257731b4f1 100644
--- a/rteval/cpusetmanager.py
+++ b/rteval/cpusetmanager.py@@ -23,7 +23,8 @@ class CpusetManager: Creates 1-2 cpusets based on configuration: - rteval_housekeeping: Only if housekeeping_cpus specified - - rteval_measurement: Always created for measurement workloads + - rteval_measurement: Created unless create_measurement is False + (e.g. --onlyload, which runs no measurement workloads) Load workloads use taskset for CPU affinity (no cpuset needed).
@@ -71,7 +72,7 @@ class CpusetManager: except Exception as e: logger.log(Log.WARN, f"Failed to clean up {cpuset_name}: {e}") - def __init__(self, housekeeping_cpus, measurement_cpus, logger, housekeeping_isolated=False): + def __init__(self, housekeeping_cpus, measurement_cpus, logger, housekeeping_isolated=False, create_measurement=True): """ Initialize cpuset manager
@@ -80,6 +81,8 @@ class CpusetManager: measurement_cpus: List of CPU integers for measurement workloads logger: rteval Log instance for logging housekeeping_isolated: If True, use partition=isolated for housekeeping (default: False = partition=member) + create_measurement: If False, skip creating the rteval_measurement cpuset + (e.g. --onlyload, which runs no measurement workloads; default: True) Note: Load workloads use taskset for CPU affinity and don't need cpusets. """
@@ -93,6 +96,7 @@ class CpusetManager: self.measurement_cpus = measurement_cpus self.logger = logger self.housekeeping_isolated = housekeeping_isolated + self.create_measurement = create_measurement # Cpuset objects (will be created in __enter__) self.housekeeping_cpuset = None
@@ -123,12 +127,14 @@ class CpusetManager: self.housekeeping_cpuset.assign_cpus(collapse_cpulist(self.housekeeping_cpus)) self.housekeeping_cpuset.write_cpu_exclusive(self.housekeeping_isolated) # partition=isolated if True, member if False - # Create measurement cpuset - self.logger.log(Log.DEBUG, f"Creating rteval_measurement cpuset with CPUs {collapse_cpulist(self.measurement_cpus)}") - self.measurement_cpuset = Cpuset('rteval_measurement') - self.measurement_cpuset.write_memnode(self.numa_nodes) - self.measurement_cpuset.assign_cpus(collapse_cpulist(self.measurement_cpus)) - self.measurement_cpuset.write_cpu_exclusive(True) # partition=isolated + # Create measurement cpuset (skipped when there are no measurement + # workloads, e.g. --onlyload) + if self.create_measurement: + self.logger.log(Log.DEBUG, f"Creating rteval_measurement cpuset with CPUs {collapse_cpulist(self.measurement_cpus)}") + self.measurement_cpuset = Cpuset('rteval_measurement') + self.measurement_cpuset.write_memnode(self.numa_nodes) + self.measurement_cpuset.assign_cpus(collapse_cpulist(self.measurement_cpus)) + self.measurement_cpuset.write_cpu_exclusive(True) # partition=isolated self.logger.log(Log.INFO, "Cpusets created successfully") return self
diff --git a/tests/test_cpusetmanager.py b/tests/test_cpusetmanager.py
index 984e0f900edf..8d69fed90443 100644
--- a/tests/test_cpusetmanager.py
+++ b/tests/test_cpusetmanager.py@@ -132,6 +132,24 @@ class TestCpusetManagerHousekeepingPartitions(unittest.TestCase): self.assertTrue(os.path.exists(measurement_path), "Measurement cpuset should exist") + def test_no_measurement_cpuset_created_when_create_measurement_false(self): + """Test that measurement cpuset is not created when create_measurement=False (e.g. --onlyload)""" + with CpusetManager( + housekeeping_cpus=[0, 1], + measurement_cpus=[2, 3], + logger=self.logger, + create_measurement=False + ) as manager: + # Check that measurement cpuset does NOT exist + measurement_path = '/sys/fs/cgroup/rteval_measurement' + self.assertFalse(os.path.exists(measurement_path), + "Measurement cpuset should not exist when create_measurement is False") + + # Check that housekeeping cpuset DOES exist + hk_path = '/sys/fs/cgroup/rteval_housekeeping' + self.assertTrue(os.path.exists(hk_path), + "Housekeeping cpuset should exist") + @unittest.skipUnless(os.geteuid() == 0, "Requires root permissions") @unittest.skipUnless(cpuset.CpusetsInit().supported, "Requires cgroup v2 support")
--
2.55.0