Esempio n. 1
0
    def get_rtapp_profile(cls, plat_info):
        profile = {}
        cpus = cls.get_migration_cpus(plat_info)

        for task in ["migr", "static0", "static1"]:
            # An empty RTATask just to sum phases up
            profile[task] = RTATask()

        common_phase_settings = dict(
            duration_s=cls.PHASE_DURATION_S,
            period_ms=cls.TASK_PERIOD_MS,
        )

        for cpu in cpus:
            # A task that will migrate to another CPU
            profile["migr"] += Periodic(
                duty_cycle_pct=cls.unscaled_utilization(plat_info, cpu, 20),
                cpus=[cpu],
                **common_phase_settings)

            # Just some tasks that won't move to get some background utilization
            profile["static0"] += Periodic(
                duty_cycle_pct=cls.unscaled_utilization(
                    plat_info, cpus[0], 30),
                cpus=[cpus[0]],
                **common_phase_settings)

            profile["static1"] += Periodic(
                duty_cycle_pct=cls.unscaled_utilization(
                    plat_info, cpus[1], 20),
                cpus=[cpus[1]],
                **common_phase_settings)

        return profile
Esempio n. 2
0
    def get_rtapp_profile(cls, plat_info):
        cpus = list(range(plat_info['cpus-count']))

        # We're pinning stuff in the first phase, so give it ample time to
        # clean the pinned logic out of balance_interval
        free_time_s = 1.1 * cls._get_max_lb_interval(plat_info)

        # Ideally we'd like the different tasks not to complete at the same time
        # (hence the "staggered" name), but this depends on a lot of factors
        # (capacity ratios, available frequencies, thermal conditions...) so the
        # best we can do is wing it.
        stagger_s = cls._get_lb_interval(plat_info) * 1.5

        profile = {}

        for cpu in cpus:
            profile[f"{cls.task_prefix}{cpu}"] = (
                Periodic(duty_cycle_pct=0,
                         duration_s=cls.IDLING_DELAY_S,
                         period_ms=cls.TASK_PERIOD_MS,
                         cpus=[cpu]) + Periodic(duty_cycle_pct=100,
                                                duration_s=cls.PIN_DELAY_S,
                                                period_ms=cls.TASK_PERIOD_MS,
                                                cpus=[cpu]) +
                Periodic(
                    duty_cycle_pct=100,
                    # Introduce staggered task completions
                    duration_s=free_time_s + cpu * stagger_s,
                    period_ms=cls.TASK_PERIOD_MS,
                    cpus=cpus))

        return profile
Esempio n. 3
0
    def get_rtapp_profile(cls, plat_info):
        cpus = list(range(plat_info['cpus-count']))

        # We're pinning stuff in the first phase, so give it ample time to
        # clean the pinned logic out of balance_interval
        free_time_s = 1.1 * cls._get_max_lb_interval(plat_info)
        stagger_s = free_time_s // (10 * len(cpus))

        profile = {}

        for cpu in cpus:
            profile["{}{}".format(cls.task_prefix, cpu)] = (
                Periodic(duty_cycle_pct=0,
                         duration_s=cls.IDLING_DELAY_S,
                         period_ms=cls.TASK_PERIOD_MS,
                         cpus=[cpu]) + Periodic(duty_cycle_pct=100,
                                                duration_s=cls.PIN_DELAY_S,
                                                period_ms=cls.TASK_PERIOD_MS,
                                                cpus=[cpu]) +
                Periodic(
                    duty_cycle_pct=100,
                    # Introduce staggered task completions
                    duration_s=free_time_s + cpu * stagger_s,
                    period_ms=cls.TASK_PERIOD_MS,
                    cpus=cpus))

        return profile
Esempio n. 4
0
    def test_invalid_composition(self):
        """Test that you can't compose tasks with a delay in the second task"""
        t1 = Periodic()
        t2 = Periodic(delay_s=1)

        # Should work fine if delayed task is the first one
        try:
            t3 = t2 + t1
        except Exception as e:
            raise AssertionError("Couldn't compose tasks: {}".format(e))

        # But not the other way around
        with self.assertRaises(ValueError):
            t3 = t1 + t2
Esempio n. 5
0
    def get_rtapp_profile(cls, plat_info):
        """
        This class method is in charge of generating an rt-app profile, to
        configure the workload that will be run using
        :meth:`lisa.tests.base.RTATestBundle.run_rtapp`.

        It can access any information in the given
        :class:`lisa.platforms.PlatformInfo` in order to obtain a workload
        tailored to the capacity of the CPUs of the target, the available
        frequencies and so on.
        """

        # Build a list of the CPU IDs that are available
        cpus = list(range(plat_info['cpus-count']))

        # The profile is a dictionary of task names (keys) to
        # lisa.wlgen.RTATask instances
        # https://lisa-linux-integrated-system-analysis.readthedocs.io/en/master/workloads.html
        profile = {}

        for cpu in cpus:
            # Compute a utilization needed to fill 50% of ``cpu`` capacity.
            util = cls.unscaled_utilization(plat_info, cpu, 50)

            # A Periodic task has a period, and a duty_cycle (which really is a
            # target utilization). LISA will run rt-app calibration if needed
            # (it can be provided by the user in the platform information)
            profile["{}_{}".format(cls.task_prefix, cpu)] = Periodic(
                duty_cycle_pct=util,
                duration_s=1,
                period_ms=cls.TASK_PERIOD_MS,
                cpus=[cpu])

        return profile
Esempio n. 6
0
    def get_rtapp_profile(cls, plat_info):
        rtapp_profile = {}
        rtapp_profile[cls.task_prefix] = Periodic(duty_cycle_pct=50,
                                                  duration_s=30,
                                                  period_ms=cls.TASK_PERIOD_MS)

        return rtapp_profile
Esempio n. 7
0
    def _get_calib_conf(self, calibration):
        profile = {"test": Periodic()}
        rtapp = RTA.by_profile(
            self.target, name='test', res_dir=self.res_dir, profile=profile,
            calibration=calibration)

        with open(rtapp.local_json) as fh:
            return json.load(fh)['global']['calibration']
Esempio n. 8
0
    def get_rtapp_profile(cls, plat_info):
        rtapp_profile = {}
        rtapp_profile['rta_stune'] = Periodic(
            duty_cycle_pct=1,
            duration_s=3,
            period_ms=16,
        )

        return rtapp_profile
Esempio n. 9
0
    def get_rtapp_profile(cls, plat_info):
        duty = cls.get_little_duty_cycle(plat_info, 50)

        rtapp_profile = {}
        rtapp_profile[cls.task_name] = Periodic(duty_cycle_pct=duty,
                                                duration_s=1,
                                                period_ms=cls.TASK_PERIOD_MS)

        return rtapp_profile
Esempio n. 10
0
    def get_rtapp_profile(cls, plat_info):
        # Four CPU's is enough to demonstrate task migration problem
        cpu_count = min(4, plat_info["cpus-count"])

        rtapp_profile = {}
        for cpu in range(cpu_count):
            rtapp_profile[f"{cls.task_prefix}{cpu}"] = Periodic(
                duty_cycle_pct=50, duration_s=30, period_ms=cls.TASK_PERIOD_MS)

        return rtapp_profile
Esempio n. 11
0
    def get_rtapp_profile(cls, plat_info):
        small_duty = cls.get_little_duty_cycle(plat_info, 50)
        big_duty = cls.get_big_duty_cycle(plat_info)

        rtapp_profile = {}

        for i in range(3):
            rtapp_profile[f"{cls.small_prefix}_{i}"] = Periodic(
                duty_cycle_pct=small_duty,
                duration_s=1,
                period_ms=cls.TASK_PERIOD_MS)

        for i in range(2):
            rtapp_profile[f"{cls.big_prefix}_{i}"] = Periodic(
                duty_cycle_pct=big_duty,
                duration_s=1,
                period_ms=cls.TASK_PERIOD_MS)

        return rtapp_profile
Esempio n. 12
0
    def get_rtapp_profile(cls, plat_info):
        littles = plat_info["capacity-classes"][0]
        duty = cls.unscaled_utilization(plat_info, littles[0], 50)

        rtapp_profile = {}
        rtapp_profile[cls.task_name] = Periodic(duty_cycle_pct=duty,
                                                duration_s=1,
                                                period_ms=cls.TASK_PERIOD_MS)

        return rtapp_profile
Esempio n. 13
0
    def get_rtapp_profile(cls, plat_info):
        duty = cls.get_big_duty_cycle(plat_info)

        rtapp_profile = {}
        for i in range(2):
            rtapp_profile[f"{cls.task_prefix}_{i}"] = Periodic(
                duty_cycle_pct=duty,
                duration_s=1,
                period_ms=cls.TASK_PERIOD_MS)

        return rtapp_profile
Esempio n. 14
0
    def get_rtapp_profile(cls, plat_info):
        bigs = plat_info["capacity-classes"][-1]
        duty = cls.unscaled_utilization(plat_info, bigs[0], 80)

        rtapp_profile = {}
        for i in range(2):
            rtapp_profile["{}_{}".format(cls.task_prefix, i)] = Periodic(
                duty_cycle_pct=duty,
                duration_s=1,
                period_ms=cls.TASK_PERIOD_MS)

        return rtapp_profile
Esempio n. 15
0
    def get_rtapp_profile(cls, plat_info):
        periods = [
            Periodic(
                duty_cycle_pct=(util / PELT_SCALE) * 100,  # util to pct
                duration_s=5,
                period_ms=cls.TASK_PERIOD_MS,
                uclamp_min=uclamp_val,
                uclamp_max=uclamp_val)
            for uclamp_val, util in cls._get_phases(plat_info)
        ]

        return {'task': functools.reduce(lambda a, b: a + b, periods)}
Esempio n. 16
0
    def get_rtapp_profile(cls, plat_info):
        duty = cls.get_little_duty_cycle(plat_info, 50)

        rtapp_profile = {}
        for i in range(3):
            rtapp_profile["{}_{}".format(cls.task_prefix, i)] = Periodic(
                duty_cycle_pct=duty,
                duration_s=1,
                period_ms=cls.TASK_PERIOD_MS
            )

        return rtapp_profile
Esempio n. 17
0
    def get_rtapp_profile(cls, plat_info):
        # Run the 50% workload on a CPU with highest capacity
        cpu = cls.get_max_capa_cpu(plat_info)

        rtapp_profile = {}
        rtapp_profile["{}_cpu{}".format(cls.task_prefix, cpu)] = Periodic(
            duty_cycle_pct=50,
            duration_s=2,
            period_ms=cls.TASK_PERIOD_MS,
            cpus=[cpu])

        return rtapp_profile
Esempio n. 18
0
    def get_rtapp_profile(cls, plat_info):
        littles = plat_info["capacity-classes"][0]
        bigs = plat_info["capacity-classes"][-1]

        small_duty = cls.unscaled_utilization(plat_info, littles[0], 50)
        big_duty = cls.unscaled_utilization(plat_info, bigs[0], 70)

        rtapp_profile = {}

        for i in range(3):
            rtapp_profile["{}_{}".format(cls.small_prefix, i)] = Periodic(
                duty_cycle_pct=small_duty,
                duration_s=1,
                period_ms=cls.TASK_PERIOD_MS)

        for i in range(2):
            rtapp_profile["{}_{}".format(cls.big_prefix, i)] = Periodic(
                duty_cycle_pct=big_duty,
                duration_s=1,
                period_ms=cls.TASK_PERIOD_MS)

        return rtapp_profile
Esempio n. 19
0
    def get_rtapp_profile(cls, plat_info):
        profile = {}
        cpus = cls.get_migration_cpus(plat_info)

        for task in ["migrating0", "migrating1"]:
            # An empty RTATask just to sum phases up
            profile[task] = RTATask()

        for i in range(2):
            # A task that will migrate from CPU A to CPU B
            profile["migrating0"] += Periodic(duty_cycle_pct=20,
                                              duration_s=cls.PHASE_DURATION_S,
                                              period_ms=cls.TASK_PERIOD_MS,
                                              cpus=[cpus[i]])

            # A task that will migrate from CPU B to CPU A
            profile["migrating1"] += Periodic(duty_cycle_pct=20,
                                              duration_s=cls.PHASE_DURATION_S,
                                              period_ms=cls.TASK_PERIOD_MS,
                                              cpus=[cpus[1 - i]])

        return profile
Esempio n. 20
0
 def get_rtapp_profile(cls, plat_info):
     cpu = plat_info['capacity-classes'][-1][0]
     rtapp_profile = {}
     rtapp_profile['rta_stune'] = Periodic(
         duty_cycle_pct=1,  # very small task, no impact on freq w/o boost
         duration_s=10,
         period_ms=16,
         cpus=[cpu],  # pin to big CPU, to focus on frequency selection
         sched_policy='FIFO'  # RT tasks have the boost holding feature so
         # the frequency should be more stable, and we
         # shouldn't go to max freq in Android
     )
     return rtapp_profile
Esempio n. 21
0
    def get_rtapp_profile(cls, plat_info, cpu):
        """
        Get a specification for a rt-app workload with the specificied duty
        cycle, pinned to the given CPU.
        """
        rtapp_profile = {}
        rtapp_profile["{}_cpu{}".format(cls.task_prefix, cpu)] = Periodic(
            duty_cycle_pct=10,
            duration_s=2,
            period_ms=cls.TASK_PERIOD_MS,
            cpus=[cpu],
        )

        return rtapp_profile
Esempio n. 22
0
    def get_rtapp_profile(cls, plat_info):
        cpus = cls.get_migration_cpus(plat_info)
        make_name = lambda i: 'migrating{}'.format(i)

        nr_tasks = len(cpus)
        profile = {make_name(i): RTATask() for i in range(nr_tasks)}

        # Define one task per CPU, and create all the possible migrations by
        # shuffling around these tasks
        for cpus_combi in itertools.permutations(cpus, r=nr_tasks):
            for i, cpu in enumerate(cpus_combi):
                profile[make_name(i)] += Periodic(
                    duty_cycle_pct=cls.unscaled_utilization(
                        plat_info, cpu, 50),
                    duration_s=cls.PHASE_DURATION_S,
                    period_ms=cls.TASK_PERIOD_MS,
                    cpus=[cpu],
                )

        return profile
Esempio n. 23
0
    def get_rtapp_profile(cls, plat_info, cpu, freq):
        """
        Get a specification for a rt-app workload with the specificied duty
        cycle, pinned to the given CPU.
        """
        freq_capa = cls._get_freq_capa(cpu, freq, plat_info)
        duty_cycle_pct = freq_capa / UTIL_SCALE * 100
        # Use half of the capacity at that OPP, so we are sure that the
        # task will fit even at the lowest OPP
        duty_cycle_pct //= 2

        rtapp_profile = {}
        rtapp_profile[f"{cls.task_prefix}{cpu}"] = Periodic(
            duty_cycle_pct=duty_cycle_pct,
            duration_s=2,
            period_ms=cls.TASK_PERIOD_MS,
            cpus=[cpu],
        )

        return rtapp_profile
Esempio n. 24
0
    def test_profile_periodic_smoke(self):
        """
        Smoketest Periodic rt-app workload

        Creates a workload using Periodic, tests that the JSON has the expected
        content, then tests that it can be run.
        """

        profile = {
            "test": Periodic(period_ms=100, duty_cycle_pct=20, duration_s=1)
        }

        exp_phases = [{
            'loop': 10,
            'run': 20000,
            'timer': {
                'period': 100000,
                'ref': 'test'
            }
        }]

        self._do_test(profile, exp_phases)
Esempio n. 25
0
    def get_rtapp_profile(cls, plat_info):
        big_cpu = plat_info["capacity-classes"][-1][0]

        task = (
            # Big task
            Periodic(
                duty_cycle_pct=75, duration_s=5, period_ms=200, cpus=[big_cpu])
            +
            # Ramp Down
            Ramp(start_pct=50,
                 end_pct=5,
                 delta_pct=20,
                 time_s=1,
                 period_ms=200,
                 cpus=[big_cpu]) +
            # Ramp Up
            Ramp(start_pct=10,
                 end_pct=60,
                 delta_pct=20,
                 time_s=1,
                 period_ms=200,
                 cpus=[big_cpu]))
        return {'test': task}
Esempio n. 26
0
from lisa.trace import FtraceCollector, Trace
from lisa.utils import setup_logging
from lisa.target import Target, TargetConf
from lisa.wlgen.rta import RTA, Periodic
from lisa.datautils import df_filter_task_ids
import pandas as pd

setup_logging()
target = Target.from_one_conf('conf/lisa/qemu_target_default.yml')
#target = Target.from_default_conf()

rtapp_profile = {}
tasks = []
for cpu in range(4):
    tasks.append("tsk{}-{}".format(cpu, cpu))
    rtapp_profile["tsk{}".format(cpu)] = Periodic(duty_cycle_pct=50,
                                                  duration_s=120)

wload = RTA.by_profile(target, "experiment_wload", rtapp_profile)

ftrace_coll = FtraceCollector(target, events=["sched_switch"])
trace_path = os.path.join(wload.res_dir, "trace.dat")
with ftrace_coll:
    wload.run()

ftrace_coll.get_trace(trace_path)
trace = Trace(trace_path, target.plat_info, events=["sched_switch"])

# sched_switch __comm  __pid  __cpu  __line prev_comm  prev_pid  prev_prio  prev_state next_comm  next_pid  next_prio
df = trace.df_events('sched_switch')[['next_pid', 'next_comm', '__cpu']]

Esempio n. 27
0
    def test_composition(self):
        """
        Test RTA task composition with __add__

        Creates a composed workload by +-ing RTATask objects, tests that the
        JSON has the expected content, then tests running the workload
        """
        light = Periodic(duty_cycle_pct=10, duration_s=1.0, period_ms=10)

        start_pct = 10
        end_pct = 90
        delta_pct = 20
        ramp = Ramp(start_pct=start_pct,
                    end_pct=end_pct,
                    delta_pct=delta_pct,
                    time_s=1,
                    period_ms=50)

        heavy = Periodic(duty_cycle_pct=90, duration_s=0.1, period_ms=100)

        profile = {"test_task": light + ramp + heavy}

        exp_phases = [
            # Light phase:
            {
                "loop": 100,
                "run": 1000,
                "timer": {
                    "period": 10000,
                    "ref": "test_task"
                }
            },
            # Ramp phases:
            {
                "loop": 20,
                "run": 5000,
                "timer": {
                    "period": 50000,
                    "ref": "test_task"
                }
            },
            {
                "loop": 20,
                "run": 15000,
                "timer": {
                    "period": 50000,
                    "ref": "test_task"
                }
            },
            {
                "loop": 20,
                "run": 25000,
                "timer": {
                    "period": 50000,
                    "ref": "test_task"
                }
            },
            {
                "loop": 20,
                "run": 35000,
                "timer": {
                    "period": 50000,
                    "ref": "test_task"
                }
            },
            {
                "loop": 20,
                "run": 45000,
                "timer": {
                    "period": 50000,
                    "ref": "test_task"
                }
            },
            # Heavy phase:
            {
                "loop": 1,
                "run": 90000,
                "timer": {
                    "period": 100000,
                    "ref": "test_task"
                }
            }
        ]

        self._do_test(profile, exp_phases)