Home | History | Annotate | Download | only in eas
      1 #    Copyright 2017-2017 ARM Limited
      2 #
      3 # Licensed under the Apache License, Version 2.0 (the "License");
      4 # you may not use this file except in compliance with the License.
      5 # You may obtain a copy of the License at
      6 #
      7 #     http://www.apache.org/licenses/LICENSE-2.0
      8 #
      9 # Unless required by applicable law or agreed to in writing, software
     10 # distributed under the License is distributed on an "AS IS" BASIS,
     11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 # See the License for the specific language governing permissions and
     13 # limitations under the License.
     14 #
     15 
     16 from bart.common.Utils import select_window
     17 
     18 from test import LisaTest, experiment_test
     19 
     20 WORKLOAD_DURATION_S = 5
     21 
     22 REQUIRED_CPU_ACTIVE_TIME_PCT = 95
     23 
     24 class HeavyLoadTest(LisaTest):
     25     """
     26     Test an EAS system under heavy load
     27 
     28     Runs N 100% RT-App threads where N is the number of CPUs, and checks that
     29     those tasks were spread across all CPUs in the system by asserting that all
     30     CPUs were fully utilized up until the first task completed.
     31     """
     32 
     33     test_conf = {
     34         'ftrace' : {
     35             'events' : ['cpu_idle', 'sched_switch'],
     36         },
     37         'modules' : ['cgroups'], # Required by freeze_userspace flag
     38     }
     39 
     40     experiments_conf = {
     41         "wloads" : {
     42             "n_heavy_tasks" : {
     43                 "type" : "rt-app",
     44                 "conf" : {
     45                     "class" : "profile",
     46                     "params" : {
     47                         "wmig" : {
     48                             "kind" : "Periodic",
     49                             "params" : {
     50                                 "duty_cycle_pct": 100,
     51                                 "duration_s": WORKLOAD_DURATION_S,
     52                             },
     53                             # Create one task for each cpu
     54                             "tasks" : "cpus",
     55                         },
     56                     },
     57                 },
     58             },
     59         },
     60         "confs" : [{
     61             'tag' : 'energy_aware',
     62             'flags' : ['ftrace', 'freeze_userspace'],
     63             'sched_features' : 'ENERGY_AWARE',
     64         }]
     65     }
     66 
     67     @classmethod
     68     def setUpClass(cls, *args, **kwargs):
     69         super(HeavyLoadTest, cls).runExperiments(*args, **kwargs)
     70 
     71     @experiment_test
     72     def test_tasks_spread(self, experiment, tasks):
     73         trace = self.get_trace(experiment)
     74         start, _ = self.get_window(experiment)
     75         end = min(self.get_end_times(experiment).values())
     76         duration = end - start
     77 
     78         total_cpu_time = 0
     79         active_proportions = []
     80         for cpu, _ in enumerate(self.target.core_names):
     81             cpu_active = trace.getCPUActiveSignal(cpu)
     82             if cpu_active is None:
     83                 raise RuntimeError(
     84                     "Couldn't get CPU-active signal. "
     85                     "Is the 'cpu_idle' ftrace event enabled in the kernel?")
     86 
     87             # Add extra events to cpu_active signal so that it matches the
     88             # window exactly
     89             new_index = sorted(cpu_active.index.tolist() + [start, end])
     90             cpu_active = cpu_active.reindex(new_index, method='ffill')
     91 
     92             active_time = trace.integrate_square_wave(cpu_active[start:end])
     93             active_proportions.append(active_time / duration)
     94 
     95         if any(a < (REQUIRED_CPU_ACTIVE_TIME_PCT / 100.)
     96                for a in active_proportions):
     97 
     98             proportions_str = ""
     99             for cpu, _ in enumerate(self.target.core_names):
    100                 proportions_str += " {:3d} {:5.1f}%\n".format(
    101                     cpu, active_proportions[cpu]*100)
    102 
    103             raise AssertionError(
    104                 "Some CPUs were less than {}% utilized\n"
    105                 " CPU active proportions:\n{}".format(
    106                     REQUIRED_CPU_ACTIVE_TIME_PCT, proportions_str))
    107