cr2: add scheduler data classes
This patch adds all the currently used scheduler data classes.
Two of the scheduler data classes (SchedLoadAvgSchedGroup and CpuFrequency)
need special handling after the trace file has been parsed. Class Base gets
a finalize_object method which can be overwritten by a derived class to
manipulate its data frame after the trace file has been parsed. The method
is called in Run::__finalize_objects.
In most use cases, either thermal or scheduler trace data has to be examined.
To further reduce the parse-time introduce a scope parameter to the __init__
method of class Run to be able to create either thermal or scheduler related
data objects in the Run object. The default behaviour is to create thermal and
scheduler data objects together.
This patch renames the test trace file trace_sched.txt to trace_empty.txt
which can be used to test behaviour if there are no matching traces in the
trace file and it creates a new trace_sched.txt file which contains one
matching trace for each scheduler data object.
It adds test cases to check the proper data frame creation for each scheduler
data object and a test case to check that for an empty trace file the
appropriate data frames remain empty.
It alters the test case TestRun::test_run_has_all_classes from checking that
the length of data frames of the thermal data objects do have is greater then
zero towards checking that the appropriate attributes of the Run object have
been created and adds test cases TestRun::test_run_has_all_classes_scope_[all,
thermal,sched] to test this for the different settings of the scope parameter.
Change-Id: I6d9e58569d5132d194ed3558c2dbfe4d5903af59
Signed-off-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
diff --git a/cr2/sched.py b/cr2/sched.py
new file mode 100644
index 0000000..c825975
--- /dev/null
+++ b/cr2/sched.py
@@ -0,0 +1,91 @@
+#!/usr/bin/python
+
+from base import Base
+
+class SchedLoadAvgSchedGroup(Base):
+ """Corresponds to Linux kernel trace event sched_load_avg_sched_group"""
+ unique_word="sched_load_avg_sg:"
+ name="sched_load_avg_sched_group"
+ _cpu_mask_column = "cpus"
+
+ def __init__(self, path=None):
+ super(SchedLoadAvgSchedGroup, self).__init__(
+ basepath=path,
+ unique_word=self.unique_word,
+ )
+
+ def finalize_object(self):
+ """This condition is necessary to force column 'cpus' to be printed
+ as 8 digits w/ leading 0
+ """
+ if self._cpu_mask_column in self.data_frame.columns:
+ self.data_frame[self._cpu_mask_column] = self.data_frame[self._cpu_mask_column].apply('{:0>8}'.format)
+
+class SchedLoadAvgTask(Base):
+ """Corresponds to Linux kernel trace event sched_load_avg_task"""
+ unique_word="sched_load_avg_task:"
+ name="sched_load_avg_task"
+
+ def __init__(self, path=None):
+ super(SchedLoadAvgTask, self).__init__(
+ basepath=path,
+ unique_word=self.unique_word,
+ )
+
+ def get_pids(self, key=""):
+ """Returns a list of (comm, pid) that contain
+ 'key' in their 'comm'."""
+ df = self.data_frame.drop_duplicates(subset=['comm','pid']).ix[:,['comm','pid']]
+
+ return df[df['comm'].str.contains(key)].values.tolist()
+
+class SchedLoadAvgCpu(Base):
+ """Corresponds to Linux kernel trace event sched_load_avg_cpu"""
+ unique_word="sched_load_avg_cpu:"
+ name="sched_load_avg_cpu"
+
+ def __init__(self, path=None):
+ super(SchedLoadAvgCpu, self).__init__(
+ basepath=path,
+ unique_word=self.unique_word,
+ )
+
+class SchedContribScaleFactor(Base):
+ """Corresponds to Linux kernel trace event sched_contrib_scale_factor"""
+ unique_word="sched_contrib_scale_f:"
+ name="sched_contrib_scale_factor"
+
+ def __init__(self, path=None):
+ super(SchedContribScaleFactor, self).__init__(
+ basepath=path,
+ unique_word=self.unique_word,
+ )
+
+class SchedCpuCapacity(Base):
+ """Corresponds to Linux kernel trace event sched_cpu_capacity"""
+ unique_word="sched_cpu_capacity:"
+ name="sched_cpu_capacity"
+
+ def __init__(self, path=None):
+ super(SchedCpuCapacity, self).__init__(
+ basepath=path,
+ unique_word=self.unique_word,
+ )
+
+class SchedCpuFrequency(Base):
+ """Corresponds to Linux kernel trace event power/cpu_frequency"""
+ unique_word="cpu_frequency:"
+ name="sched_cpu_frequency"
+
+ def __init__(self, path=None):
+ super(SchedCpuFrequency, self).__init__(
+ basepath=path,
+ unique_word=self.unique_word,
+ )
+
+ def finalize_object(self):
+ """This renaming is necessary because our cpu related pivot is 'cpu'
+ and not 'cpu_id'. Otherwise you cannot 'mix and match' with other
+ classes
+ """
+ self.data_frame.rename(columns={'cpu_id':'cpu'}, inplace=True)