Home | History | Annotate | Download | only in trace_processor
      1 #!/usr/bin/python
      2 # Copyright (C) 2018 The Android Open Source Project
      3 #
      4 # Licensed under the Apache License, Version 2.0 (the "License");
      5 # you may not use this file except in compliance with the License.
      6 # You may obtain a copy of the License at
      7 #
      8 #      http://www.apache.org/licenses/LICENSE-2.0
      9 #
     10 # Unless required by applicable law or agreed to in writing, software
     11 # distributed under the License is distributed on an "AS IS" BASIS,
     12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 # See the License for the specific language governing permissions and
     14 # limitations under the License.
     15 
     16 import argparse
     17 
     18 from google.protobuf import descriptor, descriptor_pb2, message_factory, reflection
     19 from google.protobuf.pyext import _message
     20 
     21 CLONE_THREAD = 0x00010000
     22 
     23 
     24 class Trace(object):
     25   def __init__(self, trace):
     26     self.trace = trace
     27     self.proc_map = {}
     28     self.proc_map[0] = "idle_thread"
     29 
     30   def add_system_info(self, arch=None):
     31     self.packet = self.trace.packet.add()
     32     self.packet.system_info.utsname.machine = arch
     33 
     34   def add_ftrace_packet(self, cpu):
     35     self.packet = self.trace.packet.add()
     36     self.packet.ftrace_events.cpu = cpu
     37 
     38   def __add_ftrace_event(self, ts, tid):
     39     ftrace = self.packet.ftrace_events.event.add()
     40     ftrace.timestamp = ts
     41     ftrace.pid = tid
     42     return ftrace
     43 
     44   def add_rss_stat(self, ts, tid, member, size):
     45     ftrace = self.__add_ftrace_event(ts, tid)
     46     rss_stat = ftrace.rss_stat
     47     rss_stat.member = member
     48     rss_stat.size = size
     49 
     50   def add_oom_score_update(self, ts, oom_score_adj, pid):
     51     ftrace = self.__add_ftrace_event(ts, pid)
     52     oom_score = ftrace.oom_score_adj_update
     53     oom_score.comm = self.proc_map[pid]
     54     oom_score.oom_score_adj = oom_score_adj
     55     oom_score.pid = pid
     56 
     57   def add_sched(self, ts, prev_pid, next_pid, prev_comm=None, next_comm=None):
     58     ftrace = self.__add_ftrace_event(ts, 0)
     59     ss = ftrace.sched_switch
     60     ss.prev_comm = prev_comm or self.proc_map[prev_pid]
     61     ss.prev_pid = prev_pid
     62     ss.next_pid = next_pid
     63     ss.next_comm = next_comm or self.proc_map[next_pid]
     64 
     65   def add_cpufreq(self, ts, freq, cpu):
     66     ftrace = self.__add_ftrace_event(ts, 0)
     67     cpufreq = ftrace.cpu_frequency
     68     cpufreq.state = freq
     69     cpufreq.cpu_id = cpu
     70 
     71   def add_kernel_lmk(self, ts, tid):
     72     ftrace = self.__add_ftrace_event(ts, tid)
     73     lowmemory_kill = ftrace.lowmemory_kill
     74     lowmemory_kill.pid = tid
     75 
     76   def add_sys_enter(self, ts, tid, id):
     77     ftrace = self.__add_ftrace_event(ts, tid)
     78     sys_enter = ftrace.sys_enter
     79     sys_enter.id = id
     80 
     81   def add_sys_exit(self, ts, tid, id, ret):
     82     ftrace = self.__add_ftrace_event(ts, tid)
     83     sys_exit = ftrace.sys_exit
     84     sys_exit.id = id
     85     sys_exit.ret = ret
     86 
     87   def add_newtask(self, ts, tid, new_tid, new_comm, flags):
     88     ftrace = self.__add_ftrace_event(ts, tid)
     89     newtask = ftrace.task_newtask
     90     newtask.pid = new_tid
     91     newtask.comm = new_comm
     92     newtask.clone_flags = flags
     93 
     94   def add_process_tree_packet(self, ts=None):
     95     self.packet = self.trace.packet.add()
     96     if ts is not None:
     97       self.packet.timestamp = ts
     98 
     99   def add_process(self, pid, ppid, cmdline):
    100     process = self.packet.process_tree.processes.add()
    101     process.pid = pid
    102     process.ppid = ppid
    103     process.cmdline.append(cmdline)
    104     self.proc_map[pid] = cmdline
    105 
    106   def add_thread(self, tid, tgid, cmdline):
    107     thread = self.packet.process_tree.threads.add()
    108     thread.tid = tid
    109     thread.tgid = tgid
    110     self.proc_map[tid] = cmdline
    111 
    112 
    113 def create_trace():
    114   parser = argparse.ArgumentParser()
    115   parser.add_argument(
    116       'trace_descriptor', type=str, help='location of trace descriptor')
    117   args = parser.parse_args()
    118 
    119   with open(args.trace_descriptor, "rb") as t:
    120     fileContent = t.read()
    121 
    122   file_desc_set_pb2 = descriptor_pb2.FileDescriptorSet()
    123   file_desc_set_pb2.MergeFromString(fileContent)
    124 
    125   desc_by_path = {}
    126   for f_desc_pb2 in file_desc_set_pb2.file:
    127     f_desc_pb2_encode = f_desc_pb2.SerializeToString()
    128     f_desc = descriptor.FileDescriptor(
    129         name=f_desc_pb2.name,
    130         package=f_desc_pb2.package,
    131         serialized_pb=f_desc_pb2_encode)
    132 
    133     for desc in f_desc.message_types_by_name.values():
    134       desc_by_path[desc.full_name] = desc
    135 
    136   trace = message_factory.MessageFactory().GetPrototype(
    137       desc_by_path["perfetto.protos.Trace"])()
    138   return Trace(trace)
    139