Advertisement
Guest User

Untitled

a guest
May 23rd, 2019
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.91 KB | None | 0 0
  1. import re
  2. import os
  3. import logging
  4. import nflxprofile_pb2
  5.  
  6. event_regexp = re.compile(r" +([0-9.]+): .+?:")
  7. frame_regexp = re.compile(r"^[\t ]*[0-9a-fA-F]+ (.+) \((.*?)\)$")
  8. comm_regexp = re.compile(r"^ *([^0-9]+)")
  9. idle_process = re.compile("swapper")
  10. idle_stack = re.compile("(cpuidle|cpu_idle|cpu_bringup_and_idle|native_safe_halt|xen_hypercall_sched_op|xen_hypercall_vcpu_op)")
  11. idle_regexp = re.compile("%s.*%s" % (idle_process.pattern, idle_stack.pattern))
  12.  
  13. LOGLEVEL = os.environ.get('LOGLEVEL', 'INFO')
  14.  
  15. logger = logging.getLogger()
  16. logger.setLevel(getattr(logging, LOGLEVEL))
  17.  
  18. # inverted cache for function names
  19. inverted_child_id_cache = {}
  20.  
  21.  
  22. def library2type(library):
  23. if library == "":
  24. return ""
  25. if library.startswith("/tmp/perf-"):
  26. return "jit"
  27. if library.startswith("["):
  28. return "kernel"
  29. if library.find("vmlinux") > 0:
  30. return "kernel"
  31. return "user"
  32.  
  33.  
  34. def add_to_inverted_child_id_cache(name, parent_id, child_id):
  35. try:
  36. function = inverted_child_id_cache[name]
  37. function['p'].append(parent_id)
  38. function['c'].append(child_id)
  39. except KeyError:
  40. inverted_child_id_cache[name] = {
  41. 'p': [parent_id],
  42. 'c': [child_id]
  43. }
  44.  
  45.  
  46. def find_child_node_id(nodes, node_id, child_name):
  47. try:
  48. function = inverted_child_id_cache[child_name]
  49. index = function['p'].index(node_id)
  50. return function['c'][index]
  51. except KeyError:
  52. pass
  53. except ValueError:
  54. pass
  55. return None
  56.  
  57.  
  58. def parse_from_perf(profile_iterator):
  59. # creating the new protobuf profile and initializing with root
  60. profile = nflxprofile_pb2.Profile()
  61. profile.nodes[0].function_name = 'root'
  62. profile.nodes[0].hit_count = 0
  63. profile.params['has_parent'] = 'true'
  64.  
  65. # global count for node ids
  66. id_count = 1
  67.  
  68. # sample timestamp store for delta calculation
  69. previous_ts = None
  70.  
  71. # temporary stack array for current sample
  72. stack = []
  73.  
  74. # comm for previous sample
  75. comm = None
  76.  
  77. # ts for the previous sample
  78. ts = None
  79.  
  80. for line in profile_iterator:
  81. # utf-8
  82. line = line.decode('utf-8')
  83.  
  84. # skip comments and empty lines
  85. if not line or line[0] == '#':
  86. continue
  87.  
  88. # As a performance optimization, skip an event regexp search if the
  89. # line looks like a stack trace based on starting with '\t'. This
  90. # makes a big difference.
  91. r = None
  92.  
  93. if (line[0] != '\t'):
  94. r = event_regexp.search(line)
  95. if (r): # TODO: or after last line
  96. if (stack):
  97. # process prior stack
  98. stackstr = ""
  99. for pair in stack:
  100. stackstr += pair[0] + ";"
  101. if not (idle_regexp.search(stackstr)):
  102. node_id = 0
  103. for i, pair in enumerate(stack):
  104. # Split inlined frames. "->" is used by software such as java
  105. # perf-map-agent. For example, "a->b->c" means c() is inlined in b(),
  106. # and b() is inlined in a(). This code will identify b() and c() as
  107. # the "inlined" library type, and a() as whatever the library says
  108. # it is.
  109. names = pair[0].split('->')
  110. n = 0
  111. for j, name in enumerate(names):
  112. child_id = find_child_node_id(profile.nodes, node_id, name)
  113. if child_id is not None:
  114. node = profile.nodes[child_id]
  115. node_id = child_id
  116. if i == (len(stack) - 1):
  117. # last item
  118. node.hit_count = node.hit_count + 1
  119. else:
  120. # strip leading "L" from java symbols (only reason we need comm):
  121. if (comm and comm == "java" and name.startswith("L")):
  122. name = name[1:]
  123. libtype = library2type(pair[1]) if n == 0 else "inlined"
  124. n += 1
  125. profile.nodes[id_count].function_name = name
  126. profile.nodes[id_count].hit_count = 0
  127. profile.nodes[id_count].libtype = libtype
  128. profile.nodes[id_count].parent = node_id
  129. profile.nodes[node_id].children.append(id_count) # adding children id
  130. add_to_inverted_child_id_cache(name, node_id, id_count) # adding new node to inverted node cache
  131. node_id = id_count # moving current node id to it
  132. id_count = id_count + 1 # incrementing next id
  133. profile.samples.append(node_id)
  134. if ts:
  135. if not previous_ts:
  136. profile.time_deltas.append(0)
  137. profile.start_time = ts
  138. else:
  139. profile.time_deltas.append(ts - previous_ts)
  140. previous_ts = ts
  141. profile.end_time = ts
  142. stack = []
  143. ts = float(r.group(1))
  144. r = comm_regexp.search(line)
  145. if (r):
  146. comm = r.group(1).rstrip()
  147. stack.append([comm, ""])
  148. else:
  149. stack.append(["<unknown>", ""])
  150. else:
  151. r = frame_regexp.search(line)
  152. if (r):
  153. name = r.group(1)
  154. # strip instruction offset (+0xfe200...)
  155. c = name.find("+")
  156. if (c > 0):
  157. name = name[:c]
  158. stack.insert(1, [name, r.group(2)])
  159. print("Processed {} ids.".format(str(id_count)))
  160. return profile
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement