Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(844)

Side by Side Diff: tools/android/adb_profile_chrome/perf_to_tracing.py

Issue 404543003: adb_profile_chrome: Check in perf-to-tracing conversion script (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/android/adb_profile_chrome/perf_controller_unittest.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Script for converting perf script events into tracing JSON.
2 #
3 # Generated by perf script -g python
4 # Licensed under the terms of the GNU GPL License version 2
vmiura 2014/07/17 22:51:17 Should we replace this with Chrome's license?
Sami 2014/07/18 11:19:12 I'm not sure, but I think we need to keep the lice
5
6 import json
7 import os
8 import sys
9
10 from collections import deque
11
12
13 # Categorize DSOs by component.
14 dso_to_comp = {
15 'libdvm.so': 'Java',
16 'libart.so': 'Java',
17 'libjavacore.so': 'Java',
18 'libandroid_runtime.so': 'Android',
19 'libgui.so': 'Android',
20 'libui.so': 'Android',
21 'libbinder.so': 'Android',
22 'libmemalloc.so': 'Android',
23 'libcrypto.so': 'Android',
24 'libcutils.so':'Android',
25 'libutils.so': 'Android',
26 '[kernel.kallsyms]': 'Kernel',
27 'libc.so': 'Standard Lib',
28 'libstdc++.so': 'Standard Lib',
29 'libm.so':'Standard Lib',
30 'libGLESv2_adreno.so': 'GPU Driver',
31 'libGLESv2_adreno200.so': 'GPU Driver',
32 'libq3dtools_adreno200.so': 'GPU Driver',
33 'libEGL_adreno.so': 'GPU Driver',
34 'libEGL_adreno200.so': 'GPU Driver',
35 'libEGL.so': 'GPU Driver',
36 'libgsl.so': 'GPU Driver',
37 'libGLESv2.so': 'GPU Driver',
38 'libsc-a3xx.so': 'GPU Driver',
39 'libadreno_utils.so': 'GPU Driver',
40 'eglsubAndroid.so': 'GPU Driver',
41 'gralloc.msm8960.so': 'GPU Driver',
42 'libadreno_utils': 'GPU Driver',
43 'libGLES_mali.so': 'GPU Driver',
44 'libchromeview.so': 'Chrome',
45 '[unknown]': '<unknown>',
46 '[UNKNOWN]': '<unknown>',
47 }
48
49
50 def FilterSymbolModule(module):
51 m = dso_to_comp.get(module, None)
52 if m:
53 return m
54 if module.find('libchrome.') == 0:
55 return 'Chrome'
56 if module.find('dalvik') >= 0 or module.find('@') >= 0:
57 return 'Java'
58 return module
59
60
61 def FilterSymbolName(module, orign_module, name):
62 if module == 'Java':
63 return name #orign_module
vmiura 2014/07/17 22:51:17 nit: remove comment
Sami 2014/07/18 11:19:13 Done.
64 elif module == 'GPU Driver':
65 return name # orign_module
vmiura 2014/07/17 22:51:17 nit: remove comment
Sami 2014/07/18 11:19:13 Done.
66 if name == '':
67 return orign_module + ':unknown'
68 if name[0].isdigit() or name == '(nil)':
69 return orign_module + ':unknown'
70 return name
71
72
73 class StackFrameNode:
74 def __init__(self, stack_id, name, category):
75 self.stack_id = stack_id
76 self.parent_id = 0
77 self.children = {}
78 self.category = category
79 self.name = name
80 self.samples = []
81 self.total_weight = 0.0
82 self.have_total_weight = False
83 self.parent = None
84
85 def ToDict(self, out_dict):
86 if self.stack_id:
87 node_dict = {}
88 node_dict['name'] = self.name
89 node_dict['category'] = self.category
90 if self.parent_id:
91 node_dict['parent'] = self.parent_id
92
93 out_dict[self.stack_id] = node_dict
94
95 for child in self.children.values():
96 child.ToDict(out_dict)
97 return out_dict
98
99 def GetTotalWeight(self):
100 if self.have_total_weight:
101 return self.total_weight
102 else:
103 # Sum up self samples weight, and children's total weights.
104 for s in self.samples:
105 self.total_weight += s.weight
106 for c in self.children.values():
107 self.total_weight += c.GetTotalWeight()
108 self.have_total_weight = True
109 return self.total_weight
110
111
112 class PerfSample:
113 def __init__(self, stack_id, ts, cpu, tid, weight, samp_type, comm):
114 self.stack_id = stack_id
115 self.ts = ts
116 self.cpu = cpu
117 self.tid = tid
118 self.weight = weight
119 self.type = samp_type
120 self.comm = comm
121
122 def ToDict(self):
123 ret = {}
124 ret['ts'] = self.ts / 1000.0 # Timestamp in microseconds
125 ret['tid'] = self.tid # Thread id
126 ret['cpu'] = self.cpu # Sampled CPU
127 ret['weight'] = self.weight # Sample weight
128 ret['name'] = self.type # Sample type
129 ret['comm'] = self.comm # Sample type
130 assert self.stack_id != 0
131 if self.stack_id:
132 ret['sf'] = self.stack_id # Stack frame id
133 return ret
134
135
136 samples = []
137 root_chain = StackFrameNode(0, 'root', '[unknown]')
138 next_stack_id = 1
139 tot_period = 0
140 saved_period = 0
141
142
143 def process_event(param_dict):
144 global next_stack_id
145 global saved_period
146 global tot_period
147
148 samp_comm = param_dict['comm']
149 #samp_pid = param_dict['pid']
vmiura 2014/07/17 22:51:17 nit: Remove commented line
Sami 2014/07/18 11:19:13 Done.
150 samp_tid = param_dict['tid']
151 samp_cpu = param_dict['cpu']
152 samp_ts = param_dict['time']
153 samp_period = param_dict['period']
154 samp_type = param_dict['ev_name']
155 tot_period += samp_period
156
157 # Parse call chain.
158 seen_syms = set()
159 chain = deque()
160 for cs in param_dict['cs']:
161 cs_name = cs[0]
162 cs_dso = os.path.basename(cs[1])
163 cs_category = FilterSymbolModule(cs_dso)
164 cs_name = FilterSymbolName(cs_category, cs_dso, cs_name)
165
166 if cs_category != '<unknown>' or len(chain) == 0:
167 sym = (cs_name, cs_category)
168 if sym in seen_syms:
169 while chain[0] != sym:
170 seen_syms.remove(chain[0])
171 chain.popleft()
172 else:
173 seen_syms.add(sym)
174 chain.appendleft(sym)
175
176 # Discard garbage stacktrace before __pthread_start()
177 if cs_name == '__pthread_start(void*)':
178 break
179
180 # Done reading call chain. Add to stack frame tree.
181 stack_frame = root_chain
182 for call in chain:
183 if call in stack_frame.children:
184 stack_frame = stack_frame.children[call]
185 else:
186 new_node = StackFrameNode(next_stack_id, call[0], call[1])
187 next_stack_id += 1
188 new_node.parent_id = stack_frame.stack_id
189 stack_frame.children[call] = new_node
190 stack_frame = new_node
191
192 # Save sample.
193 sample = PerfSample(stack_frame.stack_id,
194 samp_ts,
195 samp_cpu,
196 samp_tid,
197 samp_period,
198 samp_type,
199 samp_comm)
200 samples.append(sample)
201 stack_frame.samples.append(sample)
202 saved_period += samp_period
203
204
205 def trace_begin():
206 pass
207
208
209 def trace_end():
210 # Return siblings of a call tree node.
211 def GetNodeSiblings(node):
212 if not node:
213 return []
214 if not node.parent:
215 return []
216 return node.parent.children.values()
217
218 # Try to reduce misplaced stack leaves by mobing them up into sibling nodes.
vmiura 2014/07/17 22:51:17 nit: mobing -> moving
Sami 2014/07/18 11:19:13 Done.
219 def FixCallTree(node, parent):
220 # Get siblings of node's parent.
221 node.parent = parent
222 parent_siblings = GetNodeSiblings(parent)
223
224 # If parent's sibling has same node name, has no children and small weight,
225 # transplant sibling's samples into the current node.
226 for sibling in parent_siblings:
227 if sibling.name == node.name and \
228 len(sibling.children) == 0 and \
229 sibling.GetTotalWeight() <= node.GetTotalWeight() * 0.15:
230
231 # Transplant samples from sibling to current node.
232 for samp in sibling.samples:
233 samp.stack_id = node.stack_id
234 node.samples.append(samp)
235 sibling.samples = []
236 break
237
238 # Recurse child nodes.
239 for c in node.children.values():
240 FixCallTree(c, node)
241
242 FixCallTree(root_chain, None)
243
244 trace_dict = {}
245 trace_dict['samples'] = [s.ToDict() for s in samples]
246 trace_dict['stackFrames'] = root_chain.ToDict({})
247 trace_dict['traceEvents'] = []
248
249 json.dump(trace_dict, sys.stdout, indent=1)
OLDNEW
« no previous file with comments | « tools/android/adb_profile_chrome/perf_controller_unittest.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698