diff --git a/libs/wlgen/wlgen/rta.py b/libs/wlgen/wlgen/rta.py index 813b30703b51982ba353ad63278cd8d2e0f58f6b..487548c09a83079f1788d001dc869c5564e3b23d 100644 --- a/libs/wlgen/wlgen/rta.py +++ b/libs/wlgen/wlgen/rta.py @@ -20,6 +20,7 @@ import json import os import re +from tempfile import NamedTemporaryFile from collections import OrderedDict from wlgen import Workload from devlib.utils.misc import ranges_to_list @@ -167,14 +168,18 @@ class RTA(Workload): for key in pload) + "}") # Sanity check calibration values for big.LITTLE systems - if 'bl' in target.modules: - bcpu = target.bl.bigs_online[0] - lcpu = target.bl.littles_online[0] - if pload[bcpu] > pload[lcpu]: - log.warning('Calibration values reports big cores less ' - 'capable than LITTLE cores') - raise RuntimeError('Calibration failed: try again or file a bug') - bigs_speedup = ((float(pload[lcpu]) / pload[bcpu]) - 1) * 100 + if target.big_core: + bcpu = [i for i, t in enumerate(target.core_names) if t == target.big_core] + lcpu = [i for i, t in enumerate(target.core_names) if t == target.little_core] + for l in lcpu: + for b in bcpu: + if pload[b] > pload[l]: + log.warning('Calibration values reports big cores less' + ' capable than LITTLE cores') + raise RuntimeError('Calibration failed: try again or ' + 'file a bug') + + bigs_speedup = ((float(pload[lcpu[0]]) / pload[bcpu[0]]) - 1) * 100 log.info('big cores are ~%.0f%% more capable than LITTLE cores', bigs_speedup) @@ -218,14 +223,11 @@ class RTA(Workload): return 'CPU{0:d}'.format(target_cpu) - def _confCustom(self): + def _confCustom(self, tf): rtapp_conf = self.params['custom'] - self._log.info('Loading custom configuration:') - self._log.info(' %s', rtapp_conf) self.json = '{0:s}_{1:02d}.json'.format(self.name, self.exc_id) - ofile = open(self.json, 'w') calibration = self.getCalibrationConf() # Calibration can either be a string like "CPU1" or an integer, if the @@ -252,6 +254,8 @@ class RTA(Workload): "a filename or an embedded dictionary") else: # We assume we are being passed a filename instead of a dict + self._log.info('Loading custom configuration:') + self._log.info(' %s', rtapp_conf) ifile = open(rtapp_conf, 'r') for line in ifile: @@ -259,20 +263,20 @@ class RTA(Workload): raise ValueError('Workload duration not specified') for src, target in replacements.iteritems(): line = line.replace(src, target) - ofile.write(line) + tf.write(line) if isinstance(ifile, file): ifile.close() - ofile.close() + tf.close() - with open(self.json) as f: - conf = json.load(f) - for tid in conf['tasks']: + with open(tf.name) as f: + self.rta_profile = json.load(f) + for tid in self.rta_profile['tasks']: self.tasks[tid] = {'pid': -1} return self.json - def _confProfile(self): + def _confProfile(self, tf): # Sanity check for task names for task in self.params['profile'].keys(): @@ -433,9 +437,9 @@ class RTA(Workload): # Generate JSON configuration on local file self.json = '{0:s}_{1:02d}.json'.format(self.name, self.exc_id) - with open(self.json, 'w') as outfile: - json.dump(self.rta_profile, outfile, - indent=4, separators=(',', ': ')) + json.dump(self.rta_profile, tf, + indent=4, separators=(',', ': ')) + tf.close() return self.json @@ -505,14 +509,19 @@ class RTA(Workload): self.loadref = loadref - # Setup class-specific configuration - if kind == 'custom': - self._confCustom() - elif kind == 'profile': - self._confProfile() - - # Move configuration file to target - self.target.push(self.json, self.run_dir) + try: + tf = NamedTemporaryFile(delete=False) + # Setup class-specific configuration + if kind == 'custom': + self._confCustom(tf) + elif kind == 'profile': + self._confProfile(tf) + + # Move configuration file to target + self.target.push(tf.name, os.path.join(self.run_dir,self.json)) + finally: + tf.close() + os.unlink(tf.name) self.rta_cmd = self.target.executables_directory + '/rt-app' self.rta_conf = self.run_dir + '/' + self.json diff --git a/tests/eas/load_tracking.py b/tests/eas/load_tracking.py index 578ce9be5b0b6ced826b506d8c62af805ec11e36..4b551548e2483d698e6cdc9da861958ab01a8e3f 100644 --- a/tests/eas/load_tracking.py +++ b/tests/eas/load_tracking.py @@ -557,6 +557,9 @@ class _CPUMigrationBase(LisaTest): # Allowed error margin allowed_util_margin = UTIL_SCALE * 0.02 + # Dictionary that contains the description of the tasks + tasks_desc = {} + @classmethod def setUpClass(cls, *args, **kwargs): super(_CPUMigrationBase, cls).runExperiments(*args, **kwargs) @@ -581,12 +584,13 @@ class _CPUMigrationBase(LisaTest): rtapp.conf(kind='profile', params={'task{}'.format(i): task.get() for i, task in enumerate(tasks)}, run_dir=Executor.get_run_dir(test_env.target)) + cls.tasks_desc = rtapp.rta_profile['tasks'] return { 'migration': { 'type' : 'rt-app', 'conf' : { 'class' : 'custom', - 'json' : rtapp.json, + 'json' : rtapp.rta_profile, 'prefix' : 'mig_test', }, } @@ -743,6 +747,7 @@ class _CPUMigrationBase(LisaTest): def _test_util_per_cpu(self, experiment, tasks): trace = self.get_trace(experiment) + if not trace.hasEvents('sched_switch'): raise ValueError('No sched_switch events. ' 'Does the kernel support them?') @@ -750,31 +755,29 @@ class _CPUMigrationBase(LisaTest): raise ValueError('No sched_load_cfs_rq events. ' 'Does the kernel support them?') cpus = set() - # Load the JSON tasks description - tasks_desc = json.load(open(experiment.wload.params['custom']), - object_pairs_hook=OrderedDict)['tasks'] - sw_df = trace.data_frame.trace_event('sched_switch') + # Filter the event related to the tasks - sw_df = sw_df[sw_df.next_comm.isin(tasks_desc.keys())] + sw_df = trace.data_frame.trace_event('sched_switch') + sw_df = sw_df[sw_df.next_comm.isin(self.tasks_desc.keys())] util_df = trace.data_frame.trace_event('sched_load_cfs_rq') - phases = self._get_phases_names(self._get_one_task(tasks_desc, 0)) + phases = self._get_phases_names(self._get_one_task(self.tasks_desc, 0)) # Compute the interval where the signal is stable for the phases window = self._get_stable_window(sw_df, - self._get_one_task(tasks_desc, 0)) + self._get_one_task(self.tasks_desc, 0)) msg = 'Saw util {} on cpu {}, expected {} during phase {}' for phase in phases: # Get all the cpus where tasks are running during this phase - for task in tasks_desc.iteritems(): + for task in self.tasks_desc.iteritems(): cpus.update(self._get_cpus(task[1], phase)) # Get the mean utilization per CPU util_mean = self._get_util_mean(window[phase][0], window[phase][1], util_df, cpus) # Get the expected utilization per CPU - expected = self._get_util_expected(tasks_desc, cpus, phase) + expected = self._get_util_expected(self.tasks_desc, cpus, phase) # Check that the expected utilization value and the measured one # match for each CPU. diff --git a/tests/lisa/test_wlgen_rtapp.py b/tests/lisa/test_wlgen_rtapp.py index ca0d3cc2cb33281a8a62a9d4229fa7c28cd66d63..3fef89d99440a78ac68f7f5310b6b2d23b62879d 100644 --- a/tests/lisa/test_wlgen_rtapp.py +++ b/tests/lisa/test_wlgen_rtapp.py @@ -73,8 +73,7 @@ class TestRTAProfile(RTABase): run_dir=self.target_run_dir ) - with open(rtapp.json) as f: - conf = json.load(f, object_pairs_hook=OrderedDict) + conf = rtapp.rta_profile # Check that the configuration looks like we expect it to phases = conf['tasks']['my_task']['phases'].values() @@ -270,8 +269,7 @@ class TestRTACustom(RTABase): rtapp.conf(kind='custom', params=json_path, duration=5, run_dir=self.target_run_dir) - with open(rtapp.json) as f: - conf = json.load(f) + conf = rtapp.rta_profile # Convert k to str because the json loader gives us unicode strings tasks = set([str(k) for k in conf['tasks'].keys()]) @@ -315,8 +313,7 @@ class TestRTACalibrationConf(RTABase): run_dir=self.target_run_dir ) - with open(rtapp.json) as f: - return json.load(f)['global']['calibration'] + return rtapp.rta_profile['global']['calibration'] def test_calibration_conf_pload(self): """Test that the smallest pload value is used, if provided"""