aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJavi Merino <javi.merino@arm.com>2016-03-22 11:34:30 +0000
committerJavi Merino <javi.merino@arm.com>2016-03-24 11:43:41 +0000
commit46458d66cd5118b6d9cac7cb455f8dae1286b9b2 (patch)
treede18265781764b41692e763d049084d679abf936
parentce68bd04807c4833ebf27db3602c735633646b5b (diff)
downloadtrappy-46458d66cd5118b6d9cac7cb455f8dae1286b9b2.tar.gz
systrace: add a class to parse trace coming from SysTrace
The SysTrace class has the same interface as FTrace. SysTrace doesn't support raw traces. The only special thing that we have to do is skip all the HTML in the file and parse the actual trace.
-rw-r--r--tests/test_systrace.py40
-rw-r--r--tests/trace_systrace.html35
-rw-r--r--trappy/__init__.py1
-rw-r--r--trappy/ftrace.py2
-rw-r--r--trappy/systrace.py70
5 files changed, 147 insertions, 1 deletions
diff --git a/tests/test_systrace.py b/tests/test_systrace.py
new file mode 100644
index 0000000..22b9288
--- /dev/null
+++ b/tests/test_systrace.py
@@ -0,0 +1,40 @@
+# Copyright 2016 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.
+#
+
+import utils_tests
+
+import trappy
+
+class TestSystrace(utils_tests.SetupDirectory):
+
+ def __init__(self, *args, **kwargs):
+ super(TestSystrace, self).__init__(
+ [("trace_systrace.html", "trace.html")],
+ *args,
+ **kwargs)
+
+ def test_systrace_html(self):
+ """Tests parsing of a systrace embedded textual trace """
+
+ events = ["sched_switch", "sched_wakeup", "trace_event_clock_sync"]
+ trace = trappy.SysTrace("trace.html", events=events)
+
+ self.assertTrue(hasattr(trace, "sched_wakeup"))
+ self.assertEquals(len(trace.sched_wakeup.data_frame), 4)
+ self.assertTrue("target_cpu" in trace.sched_wakeup.data_frame.columns)
+
+ self.assertTrue(hasattr(trace, "trace_event_clock_sync"))
+ self.assertEquals(len(trace.trace_event_clock_sync.data_frame), 1)
+ self.assertTrue("realtime_ts" in trace.trace_event_clock_sync.data_frame.columns)
diff --git a/tests/trace_systrace.html b/tests/trace_systrace.html
new file mode 100644
index 0000000..d35e904
--- /dev/null
+++ b/tests/trace_systrace.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+#
+# Remove HTML content...
+#
+ overlay.textContent = tr.b.normalizeException(err).message;
+ overlay.title = 'Import error';
+ overlay.visible = true;
+ });
+ }
+ window.addEventListener('load', onLoad);
+ </script>
+<!-- BEGIN TRACE -->
+ <script class="trace-data" type="application/text">
+# tracer: nop
+#
+# entries-in-buffer/entries-written: 71906/71906 #P:6
+# enabled events: sched:sched_switch sched:sched_wakeup
+#
+# _-----=> irqs-off
+# / _----=> need-resched
+# | / _---=> hardirq/softirq
+# || / _--=> preempt-depth
+# ||| / delay
+# TASK-PID TGID CPU# |||| TIMESTAMP FUNCTION
+# | | | | |||| | |
+RenderThread-1143 ( 611) [004] ...1 514769.085985: tracing_mark_write: E
+com.android.systemui-611 ( 611) [001] d..5 514769.086090: sched_wakeup: comm=Binder_5 pid=679 prio=120 success=1 target_cpu=001 state=W
+atrace-15227 (15227) [000] ...1 514769.086243: tracing_mark_write: trace_event_clock_sync: realtime_ts=1448979311493
+Binder_4-280 ( 184) [000] d..5 514769.086330: sched_wakeup: comm=Binder_5 pid=1158 prio=120 success=1 target_cpu=002 state=W
+Binder_4-280 ( 184) [000] d..3 514769.086417: sched_wakeup: comm=Binder_5 pid=1158 prio=120 success=1 target_cpu=002 state=W|m
+Binder_4-280 ( 184) [000] d..4 514769.086473: sched_wakeup: comm=EventThread pid=238 prio=111 success=1 target_cpu=003 state=W
+ </script>
+<!-- END TRACE -->
+</body>
+</html>
diff --git a/trappy/__init__.py b/trappy/__init__.py
index 52c50dd..7ea1a9d 100644
--- a/trappy/__init__.py
+++ b/trappy/__init__.py
@@ -19,6 +19,7 @@ import warnings
from trappy.bare_trace import BareTrace
from trappy.compare_runs import summary_plots, compare_runs
from trappy.ftrace import FTrace
+from trappy.systrace import SysTrace
try:
from trappy.plotter.LinePlot import LinePlot
except ImportError as exc:
diff --git a/trappy/ftrace.py b/trappy/ftrace.py
index 584c936..fce5ac1 100644
--- a/trappy/ftrace.py
+++ b/trappy/ftrace.py
@@ -45,7 +45,7 @@ def _plot_freq_hists(allfreqs, what, axis, title):
class GenericFTrace(BareTrace):
"""Generic class to parse output of FTrace. This class is meant to be
-subclassed by FTrace (for parsing FTrace coming from trace-cmd)."""
+subclassed by FTrace (for parsing FTrace coming from trace-cmd) and SysTrace."""
thermal_classes = {}
diff --git a/trappy/systrace.py b/trappy/systrace.py
new file mode 100644
index 0000000..863ba0b
--- /dev/null
+++ b/trappy/systrace.py
@@ -0,0 +1,70 @@
+# Copyright 2016 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 trappy.ftrace import GenericFTrace
+
+class drop_before_trace(object):
+ """Object that, when called, returns True if the line is not part of
+the trace
+
+ We have to first look for the "<!-- BEGIN TRACE -->" and then skip
+ the headers that start with #
+
+ """
+ def __init__(self):
+ self.before_begin_trace = True
+ self.before_script_trace_data = True
+ self.before_actual_trace = True
+
+ def __call__(self, line):
+ if self.before_begin_trace:
+ if line.startswith("<!-- BEGIN TRACE -->"):
+ self.before_begin_trace = False
+ elif self.before_script_trace_data:
+ if line.startswith(' <script class="trace-data"'):
+ self.before_script_trace_data = False
+ elif not line.startswith("#"):
+ self.before_actual_trace = False
+
+ return self.before_actual_trace
+
+class SysTrace(GenericFTrace):
+ """A wrapper that parses all events of a SysTrace run
+
+ It receives the same parameters as :mod:`trappy.ftrace.FTrace`.
+
+ """
+
+ def __init__(self, path=".", name="", normalize_time=True, scope="all",
+ events=[], window=(0, None), abs_window=(0, None)):
+
+ self.trace_path = path
+
+ super(SysTrace, self).__init__(name, normalize_time, scope, events,
+ window, abs_window)
+
+ def trace_hasnt_started(self):
+ return drop_before_trace()
+
+ def trace_hasnt_finished(self):
+ """Return a function that returns True while the current line is still part of the trace
+
+ In Systrace, the first line that is not part of the trace is
+ </script>. There's a further "<!-- END TRACE -->" but there's
+ not point scanning for it, we should stop parsing as soon as
+ we see the </script>
+
+ """
+ return lambda x: not x.endswith("</script>\n")