systrace.py revision a38f1d59a8927bf305a106478c2cf1cadbd564be
1e81fdcb135d0325e3bc22fae0583555d20aae280Brendan Jackman# Copyright 2016-2017 ARM Limited 246458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino# 346458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino# Licensed under the Apache License, Version 2.0 (the "License"); 446458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino# you may not use this file except in compliance with the License. 546458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino# You may obtain a copy of the License at 646458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino# 746458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino# http://www.apache.org/licenses/LICENSE-2.0 846458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino# 946458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino# Unless required by applicable law or agreed to in writing, software 1046458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino# distributed under the License is distributed on an "AS IS" BASIS, 1146458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1246458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino# See the License for the specific language governing permissions and 1346458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino# limitations under the License. 1446458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino# 1546458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino 1646458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merinofrom trappy.ftrace import GenericFTrace 172e58198d1ea27e93a0e8c622d1ecc13be06f645fJoel Fernandesimport re 182e58198d1ea27e93a0e8c622d1ecc13be06f645fJoel Fernandes 192e58198d1ea27e93a0e8c622d1ecc13be06f645fJoel FernandesSYSTRACE_EVENT = re.compile( 20a38f1d59a8927bf305a106478c2cf1cadbd564beJoel Fernandes r'^(?P<event>[A-Z])(\|(?P<pid>\d+)\|(?P<func>[^|]*)(\|(?P<data>.*))?)?') 2146458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino 2246458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merinoclass drop_before_trace(object): 2346458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino """Object that, when called, returns True if the line is not part of 2446458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merinothe trace 2546458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino 2646458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino We have to first look for the "<!-- BEGIN TRACE -->" and then skip 2746458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino the headers that start with # 2846458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino 2946458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino """ 30ee6fb473add14fb3e2947bb57c7e1fc86c172a46Joel Fernandes def __init__(self, tracer): 3146458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino self.before_begin_trace = True 3246458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino self.before_actual_trace = True 33ee6fb473add14fb3e2947bb57c7e1fc86c172a46Joel Fernandes self.tracer = tracer 3446458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino 3546458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino def __call__(self, line): 3646458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino if self.before_begin_trace: 37459dadaf28d43f4c06c0587ff3193732b5bca1f5Leo Yan if line.startswith("<!-- BEGIN TRACE -->") or \ 38459dadaf28d43f4c06c0587ff3193732b5bca1f5Leo Yan line.startswith("<title>Android System Trace</title>"): 3946458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino self.before_begin_trace = False 40ee6fb473add14fb3e2947bb57c7e1fc86c172a46Joel Fernandes elif self.before_actual_trace: 41459dadaf28d43f4c06c0587ff3193732b5bca1f5Leo Yan if line.startswith(' <script class="trace-data"') or \ 42459dadaf28d43f4c06c0587ff3193732b5bca1f5Leo Yan line.startswith(" var linuxPerfData"): 43ee6fb473add14fb3e2947bb57c7e1fc86c172a46Joel Fernandes self.before_actual_trace = False 4446458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino 45ee6fb473add14fb3e2947bb57c7e1fc86c172a46Joel Fernandes if not self.before_actual_trace: 46ee6fb473add14fb3e2947bb57c7e1fc86c172a46Joel Fernandes base_call = super(SysTrace, self.tracer).trace_hasnt_started() 47ee6fb473add14fb3e2947bb57c7e1fc86c172a46Joel Fernandes return base_call(line) 48ee6fb473add14fb3e2947bb57c7e1fc86c172a46Joel Fernandes else: 49ee6fb473add14fb3e2947bb57c7e1fc86c172a46Joel Fernandes return True 5046458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino 5146458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merinoclass SysTrace(GenericFTrace): 5246458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino """A wrapper that parses all events of a SysTrace run 5346458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino 5446458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino It receives the same parameters as :mod:`trappy.ftrace.FTrace`. 5546458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino 5646458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino """ 5746458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino 5846458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino def __init__(self, path=".", name="", normalize_time=True, scope="all", 5946458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino events=[], window=(0, None), abs_window=(0, None)): 6046458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino 6146458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino self.trace_path = path 6246458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino 6346458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino super(SysTrace, self).__init__(name, normalize_time, scope, events, 6446458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino window, abs_window) 6546458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino 66cdae1b21d707108002b691c9bbc6da8b4d806668Patrick Bellasi try: 67cdae1b21d707108002b691c9bbc6da8b4d806668Patrick Bellasi self._cpus = 1 + self.sched_switch.data_frame["__cpu"].max() 68cdae1b21d707108002b691c9bbc6da8b4d806668Patrick Bellasi except AttributeError: 69cdae1b21d707108002b691c9bbc6da8b4d806668Patrick Bellasi pass 70cdae1b21d707108002b691c9bbc6da8b4d806668Patrick Bellasi 7146458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino def trace_hasnt_started(self): 72ee6fb473add14fb3e2947bb57c7e1fc86c172a46Joel Fernandes return drop_before_trace(self) 7346458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino 7446458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino def trace_hasnt_finished(self): 7546458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino """Return a function that returns True while the current line is still part of the trace 7646458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino 7746458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino In Systrace, the first line that is not part of the trace is 7846458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino </script>. There's a further "<!-- END TRACE -->" but there's 7946458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino not point scanning for it, we should stop parsing as soon as 8046458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino we see the </script> 8146458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino 8246458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino """ 8346458d66cd5118b6d9cac7cb455f8dae1286b9b2Javi Merino return lambda x: not x.endswith("</script>\n") 842e58198d1ea27e93a0e8c622d1ecc13be06f645fJoel Fernandes 852e58198d1ea27e93a0e8c622d1ecc13be06f645fJoel Fernandes def generate_data_dict(self, data_str): 862e58198d1ea27e93a0e8c622d1ecc13be06f645fJoel Fernandes """ Custom parsing for systrace's userspace events """ 872e58198d1ea27e93a0e8c622d1ecc13be06f645fJoel Fernandes data_dict = None 882e58198d1ea27e93a0e8c622d1ecc13be06f645fJoel Fernandes 892e58198d1ea27e93a0e8c622d1ecc13be06f645fJoel Fernandes match = SYSTRACE_EVENT.match(data_str) 902e58198d1ea27e93a0e8c622d1ecc13be06f645fJoel Fernandes if match: 912e58198d1ea27e93a0e8c622d1ecc13be06f645fJoel Fernandes data_dict = { 'event': match.group('event'), 922e58198d1ea27e93a0e8c622d1ecc13be06f645fJoel Fernandes 'pid' : match.group('pid'), 932e58198d1ea27e93a0e8c622d1ecc13be06f645fJoel Fernandes 'func' : match.group('func'), 942e58198d1ea27e93a0e8c622d1ecc13be06f645fJoel Fernandes 'data' : match.group('data') } 952e58198d1ea27e93a0e8c622d1ecc13be06f645fJoel Fernandes 962e58198d1ea27e93a0e8c622d1ecc13be06f645fJoel Fernandes return data_dict 97