Thread (9 messages) 9 messages, 1 author, 12d ago

[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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help