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

Side by Side Diff: tools/ll_prof.py

Issue 6904127: ll_prof: Reduce profiling hooks overhead from >400% to 25%. (Closed)
Patch Set: Review fixes Created 9 years, 7 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
« no previous file with comments | « src/utils.h ('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
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # 2 #
3 # Copyright 2010 the V8 project authors. All rights reserved. 3 # Copyright 2010 the V8 project authors. All rights reserved.
4 # Redistribution and use in source and binary forms, with or without 4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are 5 # modification, are permitted provided that the following conditions are
6 # met: 6 # met:
7 # 7 #
8 # * Redistributions of source code must retain the above copyright 8 # * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer. 9 # notice, this list of conditions and the following disclaimer.
10 # * Redistributions in binary form must reproduce the above 10 # * Redistributions in binary form must reproduce the above
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 if self.self_ticks_map is None: 117 if self.self_ticks_map is None:
118 self.self_ticks_map = collections.defaultdict(lambda: 0) 118 self.self_ticks_map = collections.defaultdict(lambda: 0)
119 offset = pc - self.start_address 119 offset = pc - self.start_address
120 self.self_ticks_map[offset] += 1 120 self.self_ticks_map[offset] += 1
121 121
122 def CalleeTick(self, callee): 122 def CalleeTick(self, callee):
123 if self.callee_ticks is None: 123 if self.callee_ticks is None:
124 self.callee_ticks = collections.defaultdict(lambda: 0) 124 self.callee_ticks = collections.defaultdict(lambda: 0)
125 self.callee_ticks[callee] += 1 125 self.callee_ticks[callee] += 1
126 126
127 def PrintAnnotated(self, code_info, options): 127 def PrintAnnotated(self, arch, options):
128 if self.self_ticks_map is None: 128 if self.self_ticks_map is None:
129 ticks_map = [] 129 ticks_map = []
130 else: 130 else:
131 ticks_map = self.self_ticks_map.items() 131 ticks_map = self.self_ticks_map.items()
132 # Convert the ticks map to offsets and counts arrays so that later 132 # Convert the ticks map to offsets and counts arrays so that later
133 # we can do binary search in the offsets array. 133 # we can do binary search in the offsets array.
134 ticks_map.sort(key=lambda t: t[0]) 134 ticks_map.sort(key=lambda t: t[0])
135 ticks_offsets = [t[0] for t in ticks_map] 135 ticks_offsets = [t[0] for t in ticks_map]
136 ticks_counts = [t[1] for t in ticks_map] 136 ticks_counts = [t[1] for t in ticks_map]
137 # Get a list of disassembled lines and their addresses. 137 # Get a list of disassembled lines and their addresses.
138 lines = self._GetDisasmLines(code_info, options) 138 lines = self._GetDisasmLines(arch, options)
139 if len(lines) == 0: 139 if len(lines) == 0:
140 return 140 return
141 # Print annotated lines. 141 # Print annotated lines.
142 address = lines[0][0] 142 address = lines[0][0]
143 total_count = 0 143 total_count = 0
144 for i in xrange(len(lines)): 144 for i in xrange(len(lines)):
145 start_offset = lines[i][0] - address 145 start_offset = lines[i][0] - address
146 if i == len(lines) - 1: 146 if i == len(lines) - 1:
147 end_offset = self.end_address - self.start_address 147 end_offset = self.end_address - self.start_address
148 else: 148 else:
(...skipping 18 matching lines...) Expand all
167 "Lost ticks (%d != %d) in %s" % (total_count, self.self_ticks, self) 167 "Lost ticks (%d != %d) in %s" % (total_count, self.self_ticks, self)
168 168
169 def __str__(self): 169 def __str__(self):
170 return "%s [0x%x, 0x%x) size: %d origin: %s" % ( 170 return "%s [0x%x, 0x%x) size: %d origin: %s" % (
171 self.name, 171 self.name,
172 self.start_address, 172 self.start_address,
173 self.end_address, 173 self.end_address,
174 self.end_address - self.start_address, 174 self.end_address - self.start_address,
175 self.origin) 175 self.origin)
176 176
177 def _GetDisasmLines(self, code_info, options): 177 def _GetDisasmLines(self, arch, options):
178 if self.origin == JS_ORIGIN or self.origin == JS_SNAPSHOT_ORIGIN: 178 if self.origin == JS_ORIGIN or self.origin == JS_SNAPSHOT_ORIGIN:
179 inplace = False 179 inplace = False
180 filename = options.log + ".code" 180 filename = options.log + ".ll"
181 else: 181 else:
182 inplace = True 182 inplace = True
183 filename = self.origin 183 filename = self.origin
184 return disasm.GetDisasmLines(filename, 184 return disasm.GetDisasmLines(filename,
185 self.origin_offset, 185 self.origin_offset,
186 self.end_address - self.start_address, 186 self.end_address - self.start_address,
187 code_info.arch, 187 arch,
188 inplace) 188 inplace)
189 189
190 190
191 class CodePage(object): 191 class CodePage(object):
192 """Group of adjacent code objects.""" 192 """Group of adjacent code objects."""
193 193
194 SHIFT = 12 # 4K pages 194 SHIFT = 12 # 4K pages
195 SIZE = (1 << SHIFT) 195 SIZE = (1 << SHIFT)
196 MASK = ~(SIZE - 1) 196 MASK = ~(SIZE - 1)
197 197
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 297
298 298
299 class CodeInfo(object): 299 class CodeInfo(object):
300 """Generic info about generated code objects.""" 300 """Generic info about generated code objects."""
301 301
302 def __init__(self, arch, header_size): 302 def __init__(self, arch, header_size):
303 self.arch = arch 303 self.arch = arch
304 self.header_size = header_size 304 self.header_size = header_size
305 305
306 306
307 class CodeLogReader(object): 307 class SnapshotLogReader(object):
308 """V8 code event log reader.""" 308 """V8 snapshot log reader."""
309 309
310 _CODE_INFO_RE = re.compile( 310 _SNAPSHOT_CODE_NAME_RE = re.compile(
311 r"code-info,([^,]+),(\d+)") 311 r"snapshot-code-name,(\d+),\"(.*)\"")
312 312
313 _CODE_CREATE_RE = re.compile( 313 def __init__(self, log_name):
314 r"code-creation,([^,]+),(0x[a-f0-9]+),(\d+),\"(.*)\"(?:,(0x[a-f0-9]+),([~*]) ?)?(?:,(\d+))?") 314 self.log_name = log_name
315 315
316 _CODE_MOVE_RE = re.compile( 316 def ReadNameMap(self):
317 r"code-move,(0x[a-f0-9]+),(0x[a-f0-9]+)") 317 log = open(self.log_name, "r")
318 try:
319 snapshot_pos_to_name = {}
320 for line in log:
321 match = SnapshotLogReader._SNAPSHOT_CODE_NAME_RE.match(line)
322 if match:
323 pos = int(match.group(1))
324 name = match.group(2)
325 snapshot_pos_to_name[pos] = name
326 finally:
327 log.close()
328 return snapshot_pos_to_name
318 329
319 _CODE_DELETE_RE = re.compile(
320 r"code-delete,(0x[a-f0-9]+)")
321 330
322 _SNAPSHOT_POS_RE = re.compile( 331 class LogReader(object):
323 r"snapshot-pos,(0x[a-f0-9]+),(\d+)") 332 """V8 low-level (binary) log reader."""
324 333
325 _CODE_MOVING_GC = "code-moving-gc" 334 _ARCH_TO_POINTER_TYPE_MAP = {
335 "ia32": ctypes.c_uint32,
336 "arm": ctypes.c_uint32,
337 "x64": ctypes.c_uint64
338 }
326 339
327 def __init__(self, log_name, code_map, is_snapshot, snapshot_pos_to_name): 340 _CODE_CREATE_TAG = "C"
328 self.log = open(log_name, "r") 341 _CODE_MOVE_TAG = "M"
342 _CODE_DELETE_TAG = "D"
343 _SNAPSHOT_POSITION_TAG = "P"
344 _CODE_MOVING_GC_TAG = "G"
345
346 def __init__(self, log_name, code_map, snapshot_pos_to_name):
347 self.log_file = open(log_name, "r")
348 self.log = mmap.mmap(self.log_file.fileno(), 0, mmap.MAP_PRIVATE)
349 self.log_pos = 0
329 self.code_map = code_map 350 self.code_map = code_map
330 self.is_snapshot = is_snapshot
331 self.snapshot_pos_to_name = snapshot_pos_to_name 351 self.snapshot_pos_to_name = snapshot_pos_to_name
332 self.address_to_snapshot_name = {} 352 self.address_to_snapshot_name = {}
333 353
334 def ReadCodeInfo(self): 354 self.arch = self.log[:self.log.find("\0")]
335 line = self.log.readline() or "" 355 self.log_pos += len(self.arch) + 1
336 match = CodeLogReader._CODE_INFO_RE.match(line) 356 assert self.arch in LogReader._ARCH_TO_POINTER_TYPE_MAP, \
337 assert match, "No code info in log" 357 "Unsupported architecture %s" % self.arch
338 return CodeInfo(arch=match.group(1), header_size=int(match.group(2))) 358 pointer_type = LogReader._ARCH_TO_POINTER_TYPE_MAP[self.arch]
339 359
340 def ReadUpToGC(self, code_info): 360 self.code_create_struct = LogReader._DefineStruct([
341 made_progress = False 361 ("name_size", ctypes.c_int32),
342 code_header_size = code_info.header_size 362 ("code_address", pointer_type),
343 while True: 363 ("code_size", ctypes.c_int32)])
344 line = self.log.readline()
345 if not line:
346 return made_progress
347 made_progress = True
348 364
349 if line.startswith(CodeLogReader._CODE_MOVING_GC): 365 self.code_move_struct = LogReader._DefineStruct([
366 ("from_address", pointer_type),
367 ("to_address", pointer_type)])
368
369 self.code_delete_struct = LogReader._DefineStruct([
370 ("address", pointer_type)])
371
372 self.snapshot_position_struct = LogReader._DefineStruct([
373 ("address", pointer_type),
374 ("position", ctypes.c_int32)])
375
376 def ReadUpToGC(self):
377 while self.log_pos < self.log.size():
378 tag = self.log[self.log_pos]
379 self.log_pos += 1
380
381 if tag == LogReader._CODE_MOVING_GC_TAG:
350 self.address_to_snapshot_name.clear() 382 self.address_to_snapshot_name.clear()
351 return made_progress 383 return
352 384
353 match = CodeLogReader._CODE_CREATE_RE.match(line) 385 if tag == LogReader._CODE_CREATE_TAG:
354 if match: 386 event = self.code_create_struct.from_buffer(self.log, self.log_pos)
355 start_address = int(match.group(2), 16) + code_header_size 387 self.log_pos += ctypes.sizeof(event)
356 end_address = start_address + int(match.group(3)) - code_header_size 388 start_address = event.code_address
389 end_address = start_address + event.code_size
357 if start_address in self.address_to_snapshot_name: 390 if start_address in self.address_to_snapshot_name:
358 name = self.address_to_snapshot_name[start_address] 391 name = self.address_to_snapshot_name[start_address]
359 origin = JS_SNAPSHOT_ORIGIN 392 origin = JS_SNAPSHOT_ORIGIN
360 else: 393 else:
361 tag = match.group(1) 394 name = self.log[self.log_pos:self.log_pos + event.name_size]
362 optimization_status = match.group(6)
363 func_name = match.group(4)
364 if optimization_status:
365 name = "%s:%s%s" % (tag, optimization_status, func_name)
366 else:
367 name = "%s:%s" % (tag, func_name)
368 origin = JS_ORIGIN 395 origin = JS_ORIGIN
369 if self.is_snapshot: 396 self.log_pos += event.name_size
370 origin_offset = 0 397 origin_offset = self.log_pos
371 else: 398 self.log_pos += event.code_size
372 origin_offset = int(match.group(7))
373 code = Code(name, start_address, end_address, origin, origin_offset) 399 code = Code(name, start_address, end_address, origin, origin_offset)
374 conficting_code = self.code_map.Find(start_address) 400 conficting_code = self.code_map.Find(start_address)
375 if conficting_code: 401 if conficting_code:
376 CodeLogReader._HandleCodeConflict(conficting_code, code) 402 LogReader._HandleCodeConflict(conficting_code, code)
377 # TODO(vitalyr): this warning is too noisy because of our 403 # TODO(vitalyr): this warning is too noisy because of our
378 # attempts to reconstruct code log from the snapshot. 404 # attempts to reconstruct code log from the snapshot.
379 # print >>sys.stderr, \ 405 # print >>sys.stderr, \
380 # "Warning: Skipping duplicate code log entry %s" % code 406 # "Warning: Skipping duplicate code log entry %s" % code
381 continue 407 continue
382 self.code_map.Add(code) 408 self.code_map.Add(code)
383 continue 409 continue
384 410
385 match = CodeLogReader._CODE_MOVE_RE.match(line) 411 if tag == LogReader._CODE_MOVE_TAG:
386 if match: 412 event = self.code_move_struct.from_buffer(self.log, self.log_pos)
387 old_start_address = int(match.group(1), 16) + code_header_size 413 self.log_pos += ctypes.sizeof(event)
388 new_start_address = int(match.group(2), 16) + code_header_size 414 old_start_address = event.from_address
415 new_start_address = event.to_address
389 if old_start_address == new_start_address: 416 if old_start_address == new_start_address:
390 # Skip useless code move entries. 417 # Skip useless code move entries.
391 continue 418 continue
392 code = self.code_map.Find(old_start_address) 419 code = self.code_map.Find(old_start_address)
393 if not code: 420 if not code:
394 print >>sys.stderr, "Warning: Not found %x" % old_start_address 421 print >>sys.stderr, "Warning: Not found %x" % old_start_address
395 continue 422 continue
396 assert code.start_address == old_start_address, \ 423 assert code.start_address == old_start_address, \
397 "Inexact move address %x for %s" % (old_start_address, code) 424 "Inexact move address %x for %s" % (old_start_address, code)
398 self.code_map.Remove(code) 425 self.code_map.Remove(code)
399 size = code.end_address - code.start_address 426 size = code.end_address - code.start_address
400 code.start_address = new_start_address 427 code.start_address = new_start_address
401 code.end_address = new_start_address + size 428 code.end_address = new_start_address + size
402 self.code_map.Add(code) 429 self.code_map.Add(code)
403 continue 430 continue
404 431
405 match = CodeLogReader._CODE_DELETE_RE.match(line) 432 if tag == LogReader._CODE_DELETE_TAG:
406 if match: 433 event = self.code_delete_struct.from_buffer(self.log, self.log_pos)
407 old_start_address = int(match.group(1), 16) + code_header_size 434 self.log_pos += ctypes.sizeof(event)
435 old_start_address = event.address
408 code = self.code_map.Find(old_start_address) 436 code = self.code_map.Find(old_start_address)
409 if not code: 437 if not code:
410 print >>sys.stderr, "Warning: Not found %x" % old_start_address 438 print >>sys.stderr, "Warning: Not found %x" % old_start_address
411 continue 439 continue
412 assert code.start_address == old_start_address, \ 440 assert code.start_address == old_start_address, \
413 "Inexact delete address %x for %s" % (old_start_address, code) 441 "Inexact delete address %x for %s" % (old_start_address, code)
414 self.code_map.Remove(code) 442 self.code_map.Remove(code)
415 continue 443 continue
416 444
417 match = CodeLogReader._SNAPSHOT_POS_RE.match(line) 445 if tag == LogReader._SNAPSHOT_POSITION_TAG:
418 if match: 446 event = self.snapshot_position_struct.from_buffer(self.log,
419 start_address = int(match.group(1), 16) + code_header_size 447 self.log_pos)
420 snapshot_pos = int(match.group(2)) 448 self.log_pos += ctypes.sizeof(event)
421 if self.is_snapshot: 449 start_address = event.address
422 code = self.code_map.Find(start_address) 450 snapshot_pos = event.position
423 if code: 451 if snapshot_pos in self.snapshot_pos_to_name:
424 assert code.start_address == start_address, \ 452 self.address_to_snapshot_name[start_address] = \
425 "Inexact snapshot address %x for %s" % (start_address, code) 453 self.snapshot_pos_to_name[snapshot_pos]
426 self.snapshot_pos_to_name[snapshot_pos] = code.name 454 continue
427 else: 455
428 if snapshot_pos in self.snapshot_pos_to_name: 456 assert False, "Unknown tag %s" % tag
429 self.address_to_snapshot_name[start_address] = \
430 self.snapshot_pos_to_name[snapshot_pos]
431 457
432 def Dispose(self): 458 def Dispose(self):
433 self.log.close() 459 self.log.close()
460 self.log_file.close()
461
462 @staticmethod
463 def _DefineStruct(fields):
464 class Struct(ctypes.Structure):
465 _fields_ = fields
466 return Struct
434 467
435 @staticmethod 468 @staticmethod
436 def _HandleCodeConflict(old_code, new_code): 469 def _HandleCodeConflict(old_code, new_code):
437 assert (old_code.start_address == new_code.start_address and 470 assert (old_code.start_address == new_code.start_address and
438 old_code.end_address == new_code.end_address), \ 471 old_code.end_address == new_code.end_address), \
439 "Conficting code log entries %s and %s" % (old_code, new_code) 472 "Conficting code log entries %s and %s" % (old_code, new_code)
440 CodeLogReader._UpdateNames(old_code, new_code)
441
442 @staticmethod
443 def _UpdateNames(old_code, new_code):
444 if old_code.name == new_code.name: 473 if old_code.name == new_code.name:
445 return 474 return
446 # Kludge: there are code objects with custom names that don't
447 # match their flags.
448 misnamed_code = set(["Builtin:CpuFeatures::Probe"])
449 if old_code.name in misnamed_code:
450 return
451 # Code object may be shared by a few functions. Collect the full 475 # Code object may be shared by a few functions. Collect the full
452 # set of names. 476 # set of names.
453 old_code.AddName(new_code.name) 477 old_code.AddName(new_code.name)
454 478
455 479
456 class Descriptor(object): 480 class Descriptor(object):
457 """Descriptor of a structure in the binary trace log.""" 481 """Descriptor of a structure in the binary trace log."""
458 482
459 CTYPE_MAP = { 483 CTYPE_MAP = {
460 "u16": ctypes.c_uint16, 484 "u16": ctypes.c_uint16,
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
749 start_address = int(match.group(1), 16) 773 start_address = int(match.group(1), 16)
750 end_address = start_address 774 end_address = start_address
751 name = match.group(2) 775 name = match.group(2)
752 if code: 776 if code:
753 code.end_address = start_address 777 code.end_address = start_address
754 code_map.Add(code, 16) 778 code_map.Add(code, 16)
755 code = Code(name, start_address, end_address, "kernel", 0) 779 code = Code(name, start_address, end_address, "kernel", 0)
756 return True 780 return True
757 781
758 782
759 def PrintReport(code_map, library_repo, code_info, options): 783 def PrintReport(code_map, library_repo, arch, options):
760 print "Ticks per symbol:" 784 print "Ticks per symbol:"
761 used_code = [code for code in code_map.UsedCode()] 785 used_code = [code for code in code_map.UsedCode()]
762 used_code.sort(key=lambda x: x.self_ticks, reverse=True) 786 used_code.sort(key=lambda x: x.self_ticks, reverse=True)
763 for i, code in enumerate(used_code): 787 for i, code in enumerate(used_code):
764 print "%10d %s [%s]" % (code.self_ticks, code.FullName(), code.origin) 788 print "%10d %s [%s]" % (code.self_ticks, code.FullName(), code.origin)
765 if options.disasm_all or i < options.disasm_top: 789 if options.disasm_all or i < options.disasm_top:
766 code.PrintAnnotated(code_info, options) 790 code.PrintAnnotated(arch, options)
767 print 791 print
768 print "Ticks per library:" 792 print "Ticks per library:"
769 mmap_infos = [m for m in library_repo.infos] 793 mmap_infos = [m for m in library_repo.infos]
770 mmap_infos.sort(key=lambda m: m.ticks, reverse=True) 794 mmap_infos.sort(key=lambda m: m.ticks, reverse=True)
771 for mmap_info in mmap_infos: 795 for mmap_info in mmap_infos:
772 print "%10d %s" % (mmap_info.ticks, mmap_info.unique_name) 796 print "%10d %s" % (mmap_info.ticks, mmap_info.unique_name)
773 797
774 798
775 def PrintDot(code_map, options): 799 def PrintDot(code_map, options):
776 print "digraph G {" 800 print "digraph G {"
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
818 action="store_true", 842 action="store_true",
819 help="produce dot output (WIP) [default: %default]") 843 help="produce dot output (WIP) [default: %default]")
820 parser.add_option("--quiet", "-q", 844 parser.add_option("--quiet", "-q",
821 default=False, 845 default=False,
822 action="store_true", 846 action="store_true",
823 help="no auxiliary messages [default: %default]") 847 help="no auxiliary messages [default: %default]")
824 options, args = parser.parse_args() 848 options, args = parser.parse_args()
825 849
826 if not options.quiet: 850 if not options.quiet:
827 if options.snapshot: 851 if options.snapshot:
828 print "V8 logs: %s, %s, %s.code" % (options.snapshot_log, 852 print "V8 logs: %s, %s, %s.ll" % (options.snapshot_log,
829 options.log, 853 options.log,
830 options.log) 854 options.log)
831 else: 855 else:
832 print "V8 log: %s, %s.code (no snapshot)" % (options.log, options.log) 856 print "V8 log: %s, %s.ll (no snapshot)" % (options.log, options.log)
833 print "Perf trace file: %s" % options.trace 857 print "Perf trace file: %s" % options.trace
834 858
835 # Stats. 859 # Stats.
836 events = 0 860 events = 0
837 ticks = 0 861 ticks = 0
838 missed_ticks = 0 862 missed_ticks = 0
839 really_missed_ticks = 0 863 really_missed_ticks = 0
840 mmap_time = 0 864 mmap_time = 0
841 sample_time = 0 865 sample_time = 0
842 866
843 # Initialize the log reader and get the code info. 867 # Process the snapshot log to fill the snapshot name map.
868 snapshot_name_map = {}
869 if options.snapshot:
870 snapshot_log_reader = SnapshotLogReader(log_name=options.snapshot_log)
871 snapshot_name_map = snapshot_log_reader.ReadNameMap()
872
873 # Initialize the log reader.
844 code_map = CodeMap() 874 code_map = CodeMap()
845 snapshot_name_map = {} 875 log_reader = LogReader(log_name=options.log + ".ll",
846 log_reader = CodeLogReader(log_name=options.log, 876 code_map=code_map,
847 code_map=code_map, 877 snapshot_pos_to_name=snapshot_name_map)
848 is_snapshot=False,
849 snapshot_pos_to_name=snapshot_name_map)
850 code_info = log_reader.ReadCodeInfo()
851 if not options.quiet: 878 if not options.quiet:
852 print "Generated code architecture: %s" % code_info.arch 879 print "Generated code architecture: %s" % log_reader.arch
853 print 880 print
854 881
855 # Process the snapshot log to fill the snapshot name map.
856 if options.snapshot:
857 snapshot_log_reader = CodeLogReader(log_name=options.snapshot_log,
858 code_map=CodeMap(),
859 is_snapshot=True,
860 snapshot_pos_to_name=snapshot_name_map)
861 while snapshot_log_reader.ReadUpToGC(code_info):
862 pass
863
864 # Process the code and trace logs. 882 # Process the code and trace logs.
865 library_repo = LibraryRepo() 883 library_repo = LibraryRepo()
866 log_reader.ReadUpToGC(code_info) 884 log_reader.ReadUpToGC()
867 trace_reader = TraceReader(options.trace) 885 trace_reader = TraceReader(options.trace)
868 while True: 886 while True:
869 header, offset = trace_reader.ReadEventHeader() 887 header, offset = trace_reader.ReadEventHeader()
870 if not header: 888 if not header:
871 break 889 break
872 events += 1 890 events += 1
873 if header.type == PERF_RECORD_MMAP: 891 if header.type == PERF_RECORD_MMAP:
874 start = time.time() 892 start = time.time()
875 mmap_info = trace_reader.ReadMmap(header, offset) 893 mmap_info = trace_reader.ReadMmap(header, offset)
876 if mmap_info.filename == V8_GC_FAKE_MMAP: 894 if mmap_info.filename == V8_GC_FAKE_MMAP:
877 log_reader.ReadUpToGC(code_info) 895 log_reader.ReadUpToGC()
878 else: 896 else:
879 library_repo.Load(mmap_info, code_map, options) 897 library_repo.Load(mmap_info, code_map, options)
880 mmap_time += time.time() - start 898 mmap_time += time.time() - start
881 elif header.type == PERF_RECORD_SAMPLE: 899 elif header.type == PERF_RECORD_SAMPLE:
882 ticks += 1 900 ticks += 1
883 start = time.time() 901 start = time.time()
884 sample = trace_reader.ReadSample(header, offset) 902 sample = trace_reader.ReadSample(header, offset)
885 code = code_map.Find(sample.ip) 903 code = code_map.Find(sample.ip)
886 if code: 904 if code:
887 code.Tick(sample.ip) 905 code.Tick(sample.ip)
888 else: 906 else:
889 missed_ticks += 1 907 missed_ticks += 1
890 if not library_repo.Tick(sample.ip) and not code: 908 if not library_repo.Tick(sample.ip) and not code:
891 really_missed_ticks += 1 909 really_missed_ticks += 1
892 if trace_reader.callchain_supported: 910 if trace_reader.callchain_supported:
893 for ip in sample.ips: 911 for ip in sample.ips:
894 caller_code = code_map.Find(ip) 912 caller_code = code_map.Find(ip)
895 if caller_code: 913 if caller_code:
896 if code: 914 if code:
897 caller_code.CalleeTick(code) 915 caller_code.CalleeTick(code)
898 code = caller_code 916 code = caller_code
899 sample_time += time.time() - start 917 sample_time += time.time() - start
900 918
901 if options.dot: 919 if options.dot:
902 PrintDot(code_map, options) 920 PrintDot(code_map, options)
903 else: 921 else:
904 PrintReport(code_map, library_repo, code_info, options) 922 PrintReport(code_map, library_repo, log_reader.arch, options)
905 923
906 if not options.quiet: 924 if not options.quiet:
907 print 925 print
908 print "Stats:" 926 print "Stats:"
909 print "%10d total trace events" % events 927 print "%10d total trace events" % events
910 print "%10d total ticks" % ticks 928 print "%10d total ticks" % ticks
911 print "%10d ticks not in symbols" % missed_ticks 929 print "%10d ticks not in symbols" % missed_ticks
912 print "%10d unaccounted ticks" % really_missed_ticks 930 print "%10d unaccounted ticks" % really_missed_ticks
913 print "%10d total symbols" % len([c for c in code_map.AllCode()]) 931 print "%10d total symbols" % len([c for c in code_map.AllCode()])
914 print "%10d used symbols" % len([c for c in code_map.UsedCode()]) 932 print "%10d used symbols" % len([c for c in code_map.UsedCode()])
915 print "%9.2fs library processing time" % mmap_time 933 print "%9.2fs library processing time" % mmap_time
916 print "%9.2fs tick processing time" % sample_time 934 print "%9.2fs tick processing time" % sample_time
917 935
918 log_reader.Dispose() 936 log_reader.Dispose()
919 trace_reader.Dispose() 937 trace_reader.Dispose()
OLDNEW
« no previous file with comments | « src/utils.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698