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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/android/adb_profile_chrome/perf_controller_unittest.py ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/android/adb_profile_chrome/perf_to_tracing.py
diff --git a/tools/android/adb_profile_chrome/perf_to_tracing.py b/tools/android/adb_profile_chrome/perf_to_tracing.py
new file mode 100644
index 0000000000000000000000000000000000000000..36bf058f41e0688e1aaf3a956779bbbd54420109
--- /dev/null
+++ b/tools/android/adb_profile_chrome/perf_to_tracing.py
@@ -0,0 +1,249 @@
+# Script for converting perf script events into tracing JSON.
+#
+# Generated by perf script -g python
+# 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
+
+import json
+import os
+import sys
+
+from collections import deque
+
+
+# Categorize DSOs by component.
+dso_to_comp = {
+ 'libdvm.so': 'Java',
+ 'libart.so': 'Java',
+ 'libjavacore.so': 'Java',
+ 'libandroid_runtime.so': 'Android',
+ 'libgui.so': 'Android',
+ 'libui.so': 'Android',
+ 'libbinder.so': 'Android',
+ 'libmemalloc.so': 'Android',
+ 'libcrypto.so': 'Android',
+ 'libcutils.so':'Android',
+ 'libutils.so': 'Android',
+ '[kernel.kallsyms]': 'Kernel',
+ 'libc.so': 'Standard Lib',
+ 'libstdc++.so': 'Standard Lib',
+ 'libm.so':'Standard Lib',
+ 'libGLESv2_adreno.so': 'GPU Driver',
+ 'libGLESv2_adreno200.so': 'GPU Driver',
+ 'libq3dtools_adreno200.so': 'GPU Driver',
+ 'libEGL_adreno.so': 'GPU Driver',
+ 'libEGL_adreno200.so': 'GPU Driver',
+ 'libEGL.so': 'GPU Driver',
+ 'libgsl.so': 'GPU Driver',
+ 'libGLESv2.so': 'GPU Driver',
+ 'libsc-a3xx.so': 'GPU Driver',
+ 'libadreno_utils.so': 'GPU Driver',
+ 'eglsubAndroid.so': 'GPU Driver',
+ 'gralloc.msm8960.so': 'GPU Driver',
+ 'libadreno_utils': 'GPU Driver',
+ 'libGLES_mali.so': 'GPU Driver',
+ 'libchromeview.so': 'Chrome',
+ '[unknown]': '<unknown>',
+ '[UNKNOWN]': '<unknown>',
+}
+
+
+def FilterSymbolModule(module):
+ m = dso_to_comp.get(module, None)
+ if m:
+ return m
+ if module.find('libchrome.') == 0:
+ return 'Chrome'
+ if module.find('dalvik') >= 0 or module.find('@') >= 0:
+ return 'Java'
+ return module
+
+
+def FilterSymbolName(module, orign_module, name):
+ if module == 'Java':
+ return name #orign_module
vmiura 2014/07/17 22:51:17 nit: remove comment
Sami 2014/07/18 11:19:13 Done.
+ elif module == 'GPU Driver':
+ return name # orign_module
vmiura 2014/07/17 22:51:17 nit: remove comment
Sami 2014/07/18 11:19:13 Done.
+ if name == '':
+ return orign_module + ':unknown'
+ if name[0].isdigit() or name == '(nil)':
+ return orign_module + ':unknown'
+ return name
+
+
+class StackFrameNode:
+ def __init__(self, stack_id, name, category):
+ self.stack_id = stack_id
+ self.parent_id = 0
+ self.children = {}
+ self.category = category
+ self.name = name
+ self.samples = []
+ self.total_weight = 0.0
+ self.have_total_weight = False
+ self.parent = None
+
+ def ToDict(self, out_dict):
+ if self.stack_id:
+ node_dict = {}
+ node_dict['name'] = self.name
+ node_dict['category'] = self.category
+ if self.parent_id:
+ node_dict['parent'] = self.parent_id
+
+ out_dict[self.stack_id] = node_dict
+
+ for child in self.children.values():
+ child.ToDict(out_dict)
+ return out_dict
+
+ def GetTotalWeight(self):
+ if self.have_total_weight:
+ return self.total_weight
+ else:
+ # Sum up self samples weight, and children's total weights.
+ for s in self.samples:
+ self.total_weight += s.weight
+ for c in self.children.values():
+ self.total_weight += c.GetTotalWeight()
+ self.have_total_weight = True
+ return self.total_weight
+
+
+class PerfSample:
+ def __init__(self, stack_id, ts, cpu, tid, weight, samp_type, comm):
+ self.stack_id = stack_id
+ self.ts = ts
+ self.cpu = cpu
+ self.tid = tid
+ self.weight = weight
+ self.type = samp_type
+ self.comm = comm
+
+ def ToDict(self):
+ ret = {}
+ ret['ts'] = self.ts / 1000.0 # Timestamp in microseconds
+ ret['tid'] = self.tid # Thread id
+ ret['cpu'] = self.cpu # Sampled CPU
+ ret['weight'] = self.weight # Sample weight
+ ret['name'] = self.type # Sample type
+ ret['comm'] = self.comm # Sample type
+ assert self.stack_id != 0
+ if self.stack_id:
+ ret['sf'] = self.stack_id # Stack frame id
+ return ret
+
+
+samples = []
+root_chain = StackFrameNode(0, 'root', '[unknown]')
+next_stack_id = 1
+tot_period = 0
+saved_period = 0
+
+
+def process_event(param_dict):
+ global next_stack_id
+ global saved_period
+ global tot_period
+
+ samp_comm = param_dict['comm']
+ #samp_pid = param_dict['pid']
vmiura 2014/07/17 22:51:17 nit: Remove commented line
Sami 2014/07/18 11:19:13 Done.
+ samp_tid = param_dict['tid']
+ samp_cpu = param_dict['cpu']
+ samp_ts = param_dict['time']
+ samp_period = param_dict['period']
+ samp_type = param_dict['ev_name']
+ tot_period += samp_period
+
+ # Parse call chain.
+ seen_syms = set()
+ chain = deque()
+ for cs in param_dict['cs']:
+ cs_name = cs[0]
+ cs_dso = os.path.basename(cs[1])
+ cs_category = FilterSymbolModule(cs_dso)
+ cs_name = FilterSymbolName(cs_category, cs_dso, cs_name)
+
+ if cs_category != '<unknown>' or len(chain) == 0:
+ sym = (cs_name, cs_category)
+ if sym in seen_syms:
+ while chain[0] != sym:
+ seen_syms.remove(chain[0])
+ chain.popleft()
+ else:
+ seen_syms.add(sym)
+ chain.appendleft(sym)
+
+ # Discard garbage stacktrace before __pthread_start()
+ if cs_name == '__pthread_start(void*)':
+ break
+
+ # Done reading call chain. Add to stack frame tree.
+ stack_frame = root_chain
+ for call in chain:
+ if call in stack_frame.children:
+ stack_frame = stack_frame.children[call]
+ else:
+ new_node = StackFrameNode(next_stack_id, call[0], call[1])
+ next_stack_id += 1
+ new_node.parent_id = stack_frame.stack_id
+ stack_frame.children[call] = new_node
+ stack_frame = new_node
+
+ # Save sample.
+ sample = PerfSample(stack_frame.stack_id,
+ samp_ts,
+ samp_cpu,
+ samp_tid,
+ samp_period,
+ samp_type,
+ samp_comm)
+ samples.append(sample)
+ stack_frame.samples.append(sample)
+ saved_period += samp_period
+
+
+def trace_begin():
+ pass
+
+
+def trace_end():
+ # Return siblings of a call tree node.
+ def GetNodeSiblings(node):
+ if not node:
+ return []
+ if not node.parent:
+ return []
+ return node.parent.children.values()
+
+ # 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.
+ def FixCallTree(node, parent):
+ # Get siblings of node's parent.
+ node.parent = parent
+ parent_siblings = GetNodeSiblings(parent)
+
+ # If parent's sibling has same node name, has no children and small weight,
+ # transplant sibling's samples into the current node.
+ for sibling in parent_siblings:
+ if sibling.name == node.name and \
+ len(sibling.children) == 0 and \
+ sibling.GetTotalWeight() <= node.GetTotalWeight() * 0.15:
+
+ # Transplant samples from sibling to current node.
+ for samp in sibling.samples:
+ samp.stack_id = node.stack_id
+ node.samples.append(samp)
+ sibling.samples = []
+ break
+
+ # Recurse child nodes.
+ for c in node.children.values():
+ FixCallTree(c, node)
+
+ FixCallTree(root_chain, None)
+
+ trace_dict = {}
+ trace_dict['samples'] = [s.ToDict() for s in samples]
+ trace_dict['stackFrames'] = root_chain.ToDict({})
+ trace_dict['traceEvents'] = []
+
+ json.dump(trace_dict, sys.stdout, indent=1)
« 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