From 35e03effcafcff3f785b638578f84c6a8d61b105 Mon Sep 17 00:00:00 2001 From: Brendan Jackman Date: Thu, 30 Mar 2017 11:10:23 +0100 Subject: [PATCH 1/2] tests/eas/capacity_capping: Make assertions relative to wload start time This test currently assumes when making assertions on traces that the workload started at time 0. This is probably not the case as there is a gap between starting ftrace and running the workload. Use SchedMultiAssert.getStartTime to find the true start time of the workload and then use this as a basis for migration windows when making residency assertions. --- tests/eas/capacity_capping.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/tests/eas/capacity_capping.py b/tests/eas/capacity_capping.py index 5dcb88da8..bb6d915b8 100644 --- a/tests/eas/capacity_capping.py +++ b/tests/eas/capacity_capping.py @@ -95,6 +95,8 @@ class CapacityCappingTest(unittest.TestCase): trace = trappy.FTrace(cls.trace_file) cls.sa = SchedMultiAssert(trace, cls.env.topology, execnames=cls.params.keys()) + times = cls.sa.getStartTime() + cls.wload_start_time = min(t["starttime"] for t in times.itervalues()) @classmethod def populate_params(cls): @@ -157,7 +159,8 @@ class CapacityCappingTest(unittest.TestCase): """All busy threads run in the beginning in big cpus""" phase_duration = WORKLOAD_DURATION_S / 3. - unconstrained_window = (0, phase_duration) + unconstrained_window = (self.wload_start_time, + self.wload_start_time + phase_duration) self.check_residencies(self.env.target.bl.bigs, "big", unconstrained_window, "unconstrained") @@ -165,21 +168,23 @@ class CapacityCappingTest(unittest.TestCase): """Busy threads migrate to little in the thermally constrained phase""" phase_duration = WORKLOAD_DURATION_S / 3. - migration_window = (phase_duration, phase_duration + MIGRATION_WINDOW) + mig_start = self.wload_start_time + phase_duration + mig_end = mig_start + MIGRATION_WINDOW num_tasks = len(self.params) msg = "One or more of the busy threads didn't migrate to a little cpu between {} and {}" \ - .format(migration_window[0], migration_window[1]) + .format(mig_start, mig_end) self.assertTrue(self.sa.assertSwitch("cluster", self.env.target.bl.bigs, self.env.target.bl.littles, - window=migration_window, + window=(mig_start, mig_end), rank=num_tasks), msg=msg) # The tasks must have migrated by the end of the # migration_window and they should not move until the end of # the phase. - constrained_window = (migration_window[1], 2 * phase_duration) + constrained_window = (mig_end, + self.wload_start_time + (2 * phase_duration)) self.check_residencies(self.env.target.bl.littles, "little", constrained_window, "thermally constrained") @@ -190,21 +195,21 @@ class CapacityCappingTest(unittest.TestCase): return to the big cpus""" phase_duration = WORKLOAD_DURATION_S / 3. - migration_window = (2 * phase_duration, - 2 * phase_duration + MIGRATION_WINDOW) + mig_start = self.wload_start_time + 2 * phase_duration + mig_end = mig_start + MIGRATION_WINDOW num_tasks = len(self.params) msg = "One of the busy threads didn't return to a big cpu" self.assertTrue(self.sa.assertSwitch("cluster", self.env.target.bl.littles, self.env.target.bl.bigs, - window=migration_window, + window=(mig_start, mig_end), rank=num_tasks), msg=msg) # The tasks must have migrated by the end of the # migration_window and they should continue to run on bigs # until the end of the run. - last_phase = (migration_window[1], WORKLOAD_DURATION_S) + last_phase = (mig_end, self.wload_start_time + WORKLOAD_DURATION_S) self.check_residencies(self.env.target.bl.bigs, "big", last_phase, "unconstrained") -- GitLab From d5d9a18184a496f8c96dafe8490c8951d674caa5 Mon Sep 17 00:00:00 2001 From: Brendan Jackman Date: Thu, 30 Mar 2017 11:25:54 +0100 Subject: [PATCH 2/2] tests/eas/capacity-capping: Don't let target latency influence phase times This test assumes that the artificial constraints transitioned at specific times, and uses `time.sleep` to space out these transitions. However in between these `time.sleep` calls it writes values on the target, which can take significant time. Measure the latency of this write, then subtract that latency from the time to sleep. --- tests/eas/capacity_capping.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/tests/eas/capacity_capping.py b/tests/eas/capacity_capping.py index bb6d915b8..3f828e3a5 100644 --- a/tests/eas/capacity_capping.py +++ b/tests/eas/capacity_capping.py @@ -131,11 +131,22 @@ class CapacityCappingTest(unittest.TestCase): wload.run(out_dir=cls.env.res_dir, background=True) time.sleep(phase_duration) - cls.env.target.write_value(max_freq_path, min_frequency) - time.sleep(phase_duration) - - cls.env.target.write_value(max_freq_path, max_frequency) - time.sleep(phase_duration) + # Writing values on the target can take a non-negligible amount of time. + # To prevent this from shifting the transitions between + # constrained/unconstrained phases, measure this write latency and + # reduce our sleep time by that amount. + def write_and_sleep(max_freq): + time_before = time.time() + cls.env.target.write_value(max_freq_path, max_freq) + write_latency = time.time() - time_before + if (write_latency > phase_duration): + raise ValueError( + "Latency of Target.write_value greater than phase duration! " + "Increase WORKLOAD_DURATION_S or speed up target connection") + time.sleep(phase_duration - write_latency) + + write_and_sleep(min_frequency) + write_and_sleep(max_frequency) cls.env.ftrace.stop() cls.env.ftrace.get_trace(cls.trace_file) -- GitLab