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

Side by Side Diff: tools/ll_prof.py

Issue 1796863002: Remove snapshot log parsing and option from tools. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 9 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 | « tools/gyp/v8.gyp ('k') | tools/tick-processor.html » ('j') | 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 2012 the V8 project authors. All rights reserved. 3 # Copyright 2012 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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 default. That's not enough for "-c 10000". Set it to some higher value: 59 default. That's not enough for "-c 10000". Set it to some higher value:
60 $ echo 10000000 | sudo tee /proc/sys/kernel/perf_event_max_sample_rate 60 $ echo 10000000 | sudo tee /proc/sys/kernel/perf_event_max_sample_rate
61 You can also make the warning about kernel address maps go away: 61 You can also make the warning about kernel address maps go away:
62 $ echo 0 | sudo tee /proc/sys/kernel/kptr_restrict 62 $ echo 0 | sudo tee /proc/sys/kernel/kptr_restrict
63 63
64 We have a convenience script that handles all of the above for you: 64 We have a convenience script that handles all of the above for you:
65 $ tools/run-llprof.sh ./d8 bench.js 65 $ tools/run-llprof.sh ./d8 bench.js
66 66
67 Examples: 67 Examples:
68 # Print flat profile with annotated disassembly for the 10 top 68 # Print flat profile with annotated disassembly for the 10 top
69 # symbols. Use default log names and include the snapshot log. 69 # symbols. Use default log names.
70 $ %prog --snapshot --disasm-top=10 70 $ %prog --disasm-top=10
71 71
72 # Print flat profile with annotated disassembly for all used symbols. 72 # Print flat profile with annotated disassembly for all used symbols.
73 # Use default log names and include kernel symbols into analysis. 73 # Use default log names and include kernel symbols into analysis.
74 $ %prog --disasm-all --kernel 74 $ %prog --disasm-all --kernel
75 75
76 # Print flat profile. Use custom log names. 76 # Print flat profile. Use custom log names.
77 $ %prog --log=foo.log --snapshot-log=snap-foo.log --trace=foo.data --snapshot 77 $ %prog --log=foo.log --trace=foo.data
78 """ 78 """
79 79
80 80
81 JS_ORIGIN = "js" 81 JS_ORIGIN = "js"
82 JS_SNAPSHOT_ORIGIN = "js-snapshot" 82
83 83
84 class Code(object): 84 class Code(object):
85 """Code object.""" 85 """Code object."""
86 86
87 _id = 0 87 _id = 0
88 UNKNOWN = 0 88 UNKNOWN = 0
89 V8INTERNAL = 1 89 V8INTERNAL = 1
90 FULL_CODEGEN = 2 90 FULL_CODEGEN = 2
91 OPTIMIZED = 3 91 OPTIMIZED = 3
92 92
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 192
193 def __str__(self): 193 def __str__(self):
194 return "%s [0x%x, 0x%x) size: %d origin: %s" % ( 194 return "%s [0x%x, 0x%x) size: %d origin: %s" % (
195 self.name, 195 self.name,
196 self.start_address, 196 self.start_address,
197 self.end_address, 197 self.end_address,
198 self.end_address - self.start_address, 198 self.end_address - self.start_address,
199 self.origin) 199 self.origin)
200 200
201 def _GetDisasmLines(self, arch, options): 201 def _GetDisasmLines(self, arch, options):
202 if self.origin == JS_ORIGIN or self.origin == JS_SNAPSHOT_ORIGIN: 202 inplace = True
203 inplace = False 203 filename = self.origin
204 filename = options.log + ".ll"
205 else:
206 inplace = True
207 filename = self.origin
208 return disasm.GetDisasmLines(filename, 204 return disasm.GetDisasmLines(filename,
209 self.origin_offset, 205 self.origin_offset,
210 self.end_address - self.start_address, 206 self.end_address - self.start_address,
211 arch, 207 arch,
212 inplace) 208 inplace)
213 209
214 210
215 class CodePage(object): 211 class CodePage(object):
216 """Group of adjacent code objects.""" 212 """Group of adjacent code objects."""
217 213
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 317
322 318
323 class CodeInfo(object): 319 class CodeInfo(object):
324 """Generic info about generated code objects.""" 320 """Generic info about generated code objects."""
325 321
326 def __init__(self, arch, header_size): 322 def __init__(self, arch, header_size):
327 self.arch = arch 323 self.arch = arch
328 self.header_size = header_size 324 self.header_size = header_size
329 325
330 326
331 class SnapshotLogReader(object):
332 """V8 snapshot log reader."""
333
334 _SNAPSHOT_CODE_NAME_RE = re.compile(
335 r"snapshot-code-name,(\d+),\"(.*)\"")
336
337 def __init__(self, log_name):
338 self.log_name = log_name
339
340 def ReadNameMap(self):
341 log = open(self.log_name, "r")
342 try:
343 snapshot_pos_to_name = {}
344 for line in log:
345 match = SnapshotLogReader._SNAPSHOT_CODE_NAME_RE.match(line)
346 if match:
347 pos = int(match.group(1))
348 name = match.group(2)
349 snapshot_pos_to_name[pos] = name
350 finally:
351 log.close()
352 return snapshot_pos_to_name
353
354
355 class LogReader(object): 327 class LogReader(object):
356 """V8 low-level (binary) log reader.""" 328 """V8 low-level (binary) log reader."""
357 329
358 _ARCH_TO_POINTER_TYPE_MAP = { 330 _ARCH_TO_POINTER_TYPE_MAP = {
359 "ia32": ctypes.c_uint32, 331 "ia32": ctypes.c_uint32,
360 "arm": ctypes.c_uint32, 332 "arm": ctypes.c_uint32,
361 "mips": ctypes.c_uint32, 333 "mips": ctypes.c_uint32,
362 "x64": ctypes.c_uint64, 334 "x64": ctypes.c_uint64,
363 "arm64": ctypes.c_uint64 335 "arm64": ctypes.c_uint64
364 } 336 }
365 337
366 _CODE_CREATE_TAG = "C" 338 _CODE_CREATE_TAG = "C"
367 _CODE_MOVE_TAG = "M" 339 _CODE_MOVE_TAG = "M"
368 _SNAPSHOT_POSITION_TAG = "P" 340 _SNAPSHOT_POSITION_TAG = "P"
Yang 2016/03/15 10:13:19 This is no longer necessary?
Stefano Sanfilippo 2016/04/04 16:22:30 Removed, together with all the related code.
369 _CODE_MOVING_GC_TAG = "G" 341 _CODE_MOVING_GC_TAG = "G"
370 342
371 def __init__(self, log_name, code_map, snapshot_pos_to_name): 343 def __init__(self, log_name, code_map):
372 self.log_file = open(log_name, "r") 344 self.log_file = open(log_name, "r")
373 self.log = mmap.mmap(self.log_file.fileno(), 0, mmap.MAP_PRIVATE) 345 self.log = mmap.mmap(self.log_file.fileno(), 0, mmap.MAP_PRIVATE)
374 self.log_pos = 0 346 self.log_pos = 0
375 self.code_map = code_map 347 self.code_map = code_map
376 self.snapshot_pos_to_name = snapshot_pos_to_name
377 self.address_to_snapshot_name = {}
378 348
379 self.arch = self.log[:self.log.find("\0")] 349 self.arch = self.log[:self.log.find("\0")]
380 self.log_pos += len(self.arch) + 1 350 self.log_pos += len(self.arch) + 1
381 assert self.arch in LogReader._ARCH_TO_POINTER_TYPE_MAP, \ 351 assert self.arch in LogReader._ARCH_TO_POINTER_TYPE_MAP, \
382 "Unsupported architecture %s" % self.arch 352 "Unsupported architecture %s" % self.arch
383 pointer_type = LogReader._ARCH_TO_POINTER_TYPE_MAP[self.arch] 353 pointer_type = LogReader._ARCH_TO_POINTER_TYPE_MAP[self.arch]
384 354
385 self.code_create_struct = LogReader._DefineStruct([ 355 self.code_create_struct = LogReader._DefineStruct([
386 ("name_size", ctypes.c_int32), 356 ("name_size", ctypes.c_int32),
387 ("code_address", pointer_type), 357 ("code_address", pointer_type),
388 ("code_size", ctypes.c_int32)]) 358 ("code_size", ctypes.c_int32)])
389 359
390 self.code_move_struct = LogReader._DefineStruct([ 360 self.code_move_struct = LogReader._DefineStruct([
391 ("from_address", pointer_type), 361 ("from_address", pointer_type),
392 ("to_address", pointer_type)]) 362 ("to_address", pointer_type)])
393 363
394 self.code_delete_struct = LogReader._DefineStruct([ 364 self.code_delete_struct = LogReader._DefineStruct([
395 ("address", pointer_type)]) 365 ("address", pointer_type)])
396 366
397 self.snapshot_position_struct = LogReader._DefineStruct([ 367 self.snapshot_position_struct = LogReader._DefineStruct([
398 ("address", pointer_type), 368 ("address", pointer_type),
399 ("position", ctypes.c_int32)]) 369 ("position", ctypes.c_int32)])
400 370
401 def ReadUpToGC(self): 371 def ReadUpToGC(self):
402 while self.log_pos < self.log.size(): 372 while self.log_pos < self.log.size():
403 tag = self.log[self.log_pos] 373 tag = self.log[self.log_pos]
404 self.log_pos += 1 374 self.log_pos += 1
405 375
406 if tag == LogReader._CODE_MOVING_GC_TAG: 376 if tag == LogReader._CODE_MOVING_GC_TAG:
407 self.address_to_snapshot_name.clear()
408 return 377 return
409 378
410 if tag == LogReader._CODE_CREATE_TAG: 379 if tag == LogReader._CODE_CREATE_TAG:
411 event = self.code_create_struct.from_buffer(self.log, self.log_pos) 380 event = self.code_create_struct.from_buffer(self.log, self.log_pos)
412 self.log_pos += ctypes.sizeof(event) 381 self.log_pos += ctypes.sizeof(event)
413 start_address = event.code_address 382 start_address = event.code_address
414 end_address = start_address + event.code_size 383 end_address = start_address + event.code_size
415 if start_address in self.address_to_snapshot_name: 384 name = self.log[self.log_pos:self.log_pos + event.name_size]
416 name = self.address_to_snapshot_name[start_address] 385 origin = JS_ORIGIN
417 origin = JS_SNAPSHOT_ORIGIN
418 else:
419 name = self.log[self.log_pos:self.log_pos + event.name_size]
420 origin = JS_ORIGIN
421 self.log_pos += event.name_size 386 self.log_pos += event.name_size
422 origin_offset = self.log_pos 387 origin_offset = self.log_pos
423 self.log_pos += event.code_size 388 self.log_pos += event.code_size
424 code = Code(name, start_address, end_address, origin, origin_offset) 389 code = Code(name, start_address, end_address, origin, origin_offset)
425 conficting_code = self.code_map.Find(start_address) 390 conficting_code = self.code_map.Find(start_address)
426 if conficting_code: 391 if conficting_code:
427 if not (conficting_code.start_address == code.start_address and 392 if not (conficting_code.start_address == code.start_address and
428 conficting_code.end_address == code.end_address): 393 conficting_code.end_address == code.end_address):
429 self.code_map.Remove(conficting_code) 394 self.code_map.Remove(conficting_code)
430 else: 395 else:
(...skipping 20 matching lines...) Expand all
451 continue 416 continue
452 assert code.start_address == old_start_address, \ 417 assert code.start_address == old_start_address, \
453 "Inexact move address %x for %s" % (old_start_address, code) 418 "Inexact move address %x for %s" % (old_start_address, code)
454 self.code_map.Remove(code) 419 self.code_map.Remove(code)
455 size = code.end_address - code.start_address 420 size = code.end_address - code.start_address
456 code.start_address = new_start_address 421 code.start_address = new_start_address
457 code.end_address = new_start_address + size 422 code.end_address = new_start_address + size
458 self.code_map.Add(code) 423 self.code_map.Add(code)
459 continue 424 continue
460 425
461 if tag == LogReader._SNAPSHOT_POSITION_TAG: 426 if tag == LogReader._SNAPSHOT_POSITION_TAG:
Yang 2016/03/15 10:13:19 This whole if-block could be removed?
Stefano Sanfilippo 2016/04/04 16:22:30 Done.
462 event = self.snapshot_position_struct.from_buffer(self.log, 427 event = self.snapshot_position_struct.from_buffer(self.log,
463 self.log_pos) 428 self.log_pos)
464 self.log_pos += ctypes.sizeof(event) 429 self.log_pos += ctypes.sizeof(event)
465 start_address = event.address 430 start_address = event.address
466 snapshot_pos = event.position 431 snapshot_pos = event.position
467 if snapshot_pos in self.snapshot_pos_to_name:
468 self.address_to_snapshot_name[start_address] = \
469 self.snapshot_pos_to_name[snapshot_pos]
470 continue 432 continue
471 433
472 assert False, "Unknown tag %s" % tag 434 assert False, "Unknown tag %s" % tag
473 435
474 def Dispose(self): 436 def Dispose(self):
475 self.log.close() 437 self.log.close()
476 self.log_file.close() 438 self.log_file.close()
477 439
478 @staticmethod 440 @staticmethod
479 def _DefineStruct(fields): 441 def _DefineStruct(fields):
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after
877 continue 839 continue
878 print "n%d [shape=box,label=\"%s\"];" % (code.id, code.name) 840 print "n%d [shape=box,label=\"%s\"];" % (code.id, code.name)
879 if code.callee_ticks: 841 if code.callee_ticks:
880 for callee, ticks in code.callee_ticks.iteritems(): 842 for callee, ticks in code.callee_ticks.iteritems():
881 print "n%d -> n%d [label=\"%d\"];" % (code.id, callee.id, ticks) 843 print "n%d -> n%d [label=\"%d\"];" % (code.id, callee.id, ticks)
882 print "}" 844 print "}"
883 845
884 846
885 if __name__ == "__main__": 847 if __name__ == "__main__":
886 parser = optparse.OptionParser(USAGE) 848 parser = optparse.OptionParser(USAGE)
887 parser.add_option("--snapshot-log",
888 default="obj/release/snapshot.log",
889 help="V8 snapshot log file name [default: %default]")
890 parser.add_option("--log", 849 parser.add_option("--log",
891 default="v8.log", 850 default="v8.log",
892 help="V8 log file name [default: %default]") 851 help="V8 log file name [default: %default]")
893 parser.add_option("--snapshot",
894 default=False,
895 action="store_true",
896 help="process V8 snapshot log [default: %default]")
897 parser.add_option("--trace", 852 parser.add_option("--trace",
898 default="perf.data", 853 default="perf.data",
899 help="perf trace file name [default: %default]") 854 help="perf trace file name [default: %default]")
900 parser.add_option("--kernel", 855 parser.add_option("--kernel",
901 default=False, 856 default=False,
902 action="store_true", 857 action="store_true",
903 help="process kernel entries [default: %default]") 858 help="process kernel entries [default: %default]")
904 parser.add_option("--disasm-top", 859 parser.add_option("--disasm-top",
905 default=0, 860 default=0,
906 type="int", 861 type="int",
(...skipping 17 matching lines...) Expand all
924 help="gc fake mmap file [default: %default]") 879 help="gc fake mmap file [default: %default]")
925 parser.add_option("--objdump", 880 parser.add_option("--objdump",
926 default="/usr/bin/objdump", 881 default="/usr/bin/objdump",
927 help="objdump tool to use [default: %default]") 882 help="objdump tool to use [default: %default]")
928 parser.add_option("--host-root", 883 parser.add_option("--host-root",
929 default="", 884 default="",
930 help="Path to the host root [default: %default]") 885 help="Path to the host root [default: %default]")
931 options, args = parser.parse_args() 886 options, args = parser.parse_args()
932 887
933 if not options.quiet: 888 if not options.quiet:
934 if options.snapshot: 889 print "V8 log: %s, %s.ll" % (options.log, options.log)
935 print "V8 logs: %s, %s, %s.ll" % (options.snapshot_log,
936 options.log,
937 options.log)
938 else:
939 print "V8 log: %s, %s.ll (no snapshot)" % (options.log, options.log)
940 print "Perf trace file: %s" % options.trace 890 print "Perf trace file: %s" % options.trace
941 891
942 V8_GC_FAKE_MMAP = options.gc_fake_mmap 892 V8_GC_FAKE_MMAP = options.gc_fake_mmap
943 HOST_ROOT = options.host_root 893 HOST_ROOT = options.host_root
944 if os.path.exists(options.objdump): 894 if os.path.exists(options.objdump):
945 disasm.OBJDUMP_BIN = options.objdump 895 disasm.OBJDUMP_BIN = options.objdump
946 OBJDUMP_BIN = options.objdump 896 OBJDUMP_BIN = options.objdump
947 else: 897 else:
948 print "Cannot find %s, falling back to default objdump" % options.objdump 898 print "Cannot find %s, falling back to default objdump" % options.objdump
949 899
950 # Stats. 900 # Stats.
951 events = 0 901 events = 0
952 ticks = 0 902 ticks = 0
953 missed_ticks = 0 903 missed_ticks = 0
954 really_missed_ticks = 0 904 really_missed_ticks = 0
955 optimized_ticks = 0 905 optimized_ticks = 0
956 generated_ticks = 0 906 generated_ticks = 0
957 v8_internal_ticks = 0 907 v8_internal_ticks = 0
958 mmap_time = 0 908 mmap_time = 0
959 sample_time = 0 909 sample_time = 0
960 910
961 # Process the snapshot log to fill the snapshot name map.
962 snapshot_name_map = {}
963 if options.snapshot:
964 snapshot_log_reader = SnapshotLogReader(log_name=options.snapshot_log)
965 snapshot_name_map = snapshot_log_reader.ReadNameMap()
966
967 # Initialize the log reader. 911 # Initialize the log reader.
968 code_map = CodeMap() 912 code_map = CodeMap()
969 log_reader = LogReader(log_name=options.log + ".ll", 913 log_reader = LogReader(log_name=options.log + ".ll",
970 code_map=code_map, 914 code_map=code_map)
971 snapshot_pos_to_name=snapshot_name_map)
972 if not options.quiet: 915 if not options.quiet:
973 print "Generated code architecture: %s" % log_reader.arch 916 print "Generated code architecture: %s" % log_reader.arch
974 print 917 print
975 sys.stdout.flush() 918 sys.stdout.flush()
976 919
977 # Process the code and trace logs. 920 # Process the code and trace logs.
978 library_repo = LibraryRepo() 921 library_repo = LibraryRepo()
979 log_reader.ReadUpToGC() 922 log_reader.ReadUpToGC()
980 trace_reader = TraceReader(options.trace) 923 trace_reader = TraceReader(options.trace)
981 while True: 924 while True:
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1046 PrintTicks(optimized_ticks, ticks, "ticks in optimized code") 989 PrintTicks(optimized_ticks, ticks, "ticks in optimized code")
1047 PrintTicks(generated_ticks, ticks, "ticks in other lazily compiled code") 990 PrintTicks(generated_ticks, ticks, "ticks in other lazily compiled code")
1048 PrintTicks(v8_internal_ticks, ticks, "ticks in v8::internal::*") 991 PrintTicks(v8_internal_ticks, ticks, "ticks in v8::internal::*")
1049 print "%10d total symbols" % len([c for c in code_map.AllCode()]) 992 print "%10d total symbols" % len([c for c in code_map.AllCode()])
1050 print "%10d used symbols" % len([c for c in code_map.UsedCode()]) 993 print "%10d used symbols" % len([c for c in code_map.UsedCode()])
1051 print "%9.2fs library processing time" % mmap_time 994 print "%9.2fs library processing time" % mmap_time
1052 print "%9.2fs tick processing time" % sample_time 995 print "%9.2fs tick processing time" % sample_time
1053 996
1054 log_reader.Dispose() 997 log_reader.Dispose()
1055 trace_reader.Dispose() 998 trace_reader.Dispose()
OLDNEW
« no previous file with comments | « tools/gyp/v8.gyp ('k') | tools/tick-processor.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698