# Copyright 2017-2017 ARM Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from bart.common.Utils import select_window
from test import LisaTest, experiment_test
WORKLOAD_DURATION_S = 5
REQUIRED_CPU_ACTIVE_TIME_PCT = 95
class HeavyLoadTest(LisaTest):
"""
Test an EAS system under heavy load
Runs N 100% RT-App threads where N is the number of CPUs, and checks that
those tasks were spread across all CPUs in the system by asserting that all
CPUs were fully utilized up until the first task completed.
"""
test_conf = {
'ftrace' : {
'events' : ['cpu_idle', 'sched_switch'],
},
'modules' : ['cgroups'], # Required by freeze_userspace flag
}
experiments_conf = {
"wloads" : {
"n_heavy_tasks" : {
"type" : "rt-app",
"conf" : {
"class" : "profile",
"params" : {
"wmig" : {
"kind" : "Periodic",
"params" : {
"duty_cycle_pct": 100,
"duration_s": WORKLOAD_DURATION_S,
},
# Create one task for each cpu
"tasks" : "cpus",
},
},
},
},
},
"confs" : [{
'tag' : 'energy_aware',
'flags' : ['ftrace', 'freeze_userspace'],
'sched_features' : 'ENERGY_AWARE',
}]
}
@classmethod
def setUpClass(cls, *args, **kwargs):
super(HeavyLoadTest, cls).runExperiments(*args, **kwargs)
@experiment_test
def test_tasks_spread(self, experiment, tasks):
trace = self.get_trace(experiment)
start, _ = self.get_window(experiment)
end = min(self.get_end_times(experiment).values())
duration = end - start
total_cpu_time = 0
active_proportions = []
for cpu, _ in enumerate(self.target.core_names):
cpu_active = trace.getCPUActiveSignal(cpu)
if cpu_active is None:
raise RuntimeError(
"Couldn't get CPU-active signal. "
"Is the 'cpu_idle' ftrace event enabled in the kernel?")
# Add extra events to cpu_active signal so that it matches the
# window exactly
new_index = sorted(cpu_active.index.tolist() + [start, end])
cpu_active = cpu_active.reindex(new_index, method='ffill')
active_time = trace.integrate_square_wave(cpu_active[start:end])
active_proportions.append(active_time / duration)
if any(a < (REQUIRED_CPU_ACTIVE_TIME_PCT / 100.)
for a in active_proportions):
proportions_str = ""
for cpu, _ in enumerate(self.target.core_names):
proportions_str += " {:3d} {:5.1f}%\n".format(
cpu, active_proportions[cpu]*100)
raise AssertionError(
"Some CPUs were less than {}% utilized\n"
" CPU active proportions:\n{}".format(
REQUIRED_CPU_ACTIVE_TIME_PCT, proportions_str))