OLD | NEW |
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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 | 61 |
62 # Print flat profile with annotated disassembly for all used symbols. | 62 # Print flat profile with annotated disassembly for all used symbols. |
63 # Use default log names and include kernel symbols into analysis. | 63 # Use default log names and include kernel symbols into analysis. |
64 $ %prog --disasm-all --kernel | 64 $ %prog --disasm-all --kernel |
65 | 65 |
66 # Print flat profile. Use custom log names. | 66 # Print flat profile. Use custom log names. |
67 $ %prog --log=foo.log --snapshot-log=snap-foo.log --trace=foo.data --snapshot | 67 $ %prog --log=foo.log --snapshot-log=snap-foo.log --trace=foo.data --snapshot |
68 """ | 68 """ |
69 | 69 |
70 | 70 |
71 # Must match kGcFakeMmap. | |
72 V8_GC_FAKE_MMAP = "/tmp/__v8_gc__" | |
73 | |
74 JS_ORIGIN = "js" | 71 JS_ORIGIN = "js" |
75 JS_SNAPSHOT_ORIGIN = "js-snapshot" | 72 JS_SNAPSHOT_ORIGIN = "js-snapshot" |
76 | 73 |
77 OBJDUMP_BIN = disasm.OBJDUMP_BIN | |
78 | |
79 | |
80 class Code(object): | 74 class Code(object): |
81 """Code object.""" | 75 """Code object.""" |
82 | 76 |
83 _id = 0 | 77 _id = 0 |
84 | 78 |
85 def __init__(self, name, start_address, end_address, origin, origin_offset): | 79 def __init__(self, name, start_address, end_address, origin, origin_offset): |
86 self.id = Code._id | 80 self.id = Code._id |
87 Code._id += 1 | 81 Code._id += 1 |
88 self.name = name | 82 self.name = name |
89 self.other_names = None | 83 self.other_names = None |
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
632 header = PERF_EVENT_HEADER_DESC.Read(self.trace, self.offset) | 626 header = PERF_EVENT_HEADER_DESC.Read(self.trace, self.offset) |
633 self.offset += header.size | 627 self.offset += header.size |
634 return header, offset | 628 return header, offset |
635 | 629 |
636 def ReadMmap(self, header, offset): | 630 def ReadMmap(self, header, offset): |
637 mmap_info = PERF_MMAP_EVENT_BODY_DESC.Read(self.trace, | 631 mmap_info = PERF_MMAP_EVENT_BODY_DESC.Read(self.trace, |
638 offset + self.header_size) | 632 offset + self.header_size) |
639 # Read null-terminated filename. | 633 # Read null-terminated filename. |
640 filename = self.trace[offset + self.header_size + ctypes.sizeof(mmap_info): | 634 filename = self.trace[offset + self.header_size + ctypes.sizeof(mmap_info): |
641 offset + header.size] | 635 offset + header.size] |
642 mmap_info.filename = filename[:filename.find(chr(0))] | 636 mmap_info.filename = HOST_ROOT + filename[:filename.find(chr(0))] |
643 return mmap_info | 637 return mmap_info |
644 | 638 |
645 def ReadSample(self, header, offset): | 639 def ReadSample(self, header, offset): |
646 sample = self.sample_event_body_desc.Read(self.trace, | 640 sample = self.sample_event_body_desc.Read(self.trace, |
647 offset + self.header_size) | 641 offset + self.header_size) |
648 if not self.callchain_supported: | 642 if not self.callchain_supported: |
649 return sample | 643 return sample |
650 sample.ips = [] | 644 sample.ips = [] |
651 offset += self.header_size + ctypes.sizeof(sample) | 645 offset += self.header_size + ctypes.sizeof(sample) |
652 for _ in xrange(sample.nr): | 646 for _ in xrange(sample.nr): |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
851 help=("disassemble and annotate all used symbols " | 845 help=("disassemble and annotate all used symbols " |
852 "[default: %default]")) | 846 "[default: %default]")) |
853 parser.add_option("--dot", | 847 parser.add_option("--dot", |
854 default=False, | 848 default=False, |
855 action="store_true", | 849 action="store_true", |
856 help="produce dot output (WIP) [default: %default]") | 850 help="produce dot output (WIP) [default: %default]") |
857 parser.add_option("--quiet", "-q", | 851 parser.add_option("--quiet", "-q", |
858 default=False, | 852 default=False, |
859 action="store_true", | 853 action="store_true", |
860 help="no auxiliary messages [default: %default]") | 854 help="no auxiliary messages [default: %default]") |
| 855 parser.add_option("--gc-fake-mmap", |
| 856 default="/tmp/__v8_gc__", |
| 857 help="gc fake mmap file [default: %default]") |
| 858 parser.add_option("--objdump", |
| 859 default="/usr/bin/objdump", |
| 860 help="objdump tool to use [default: %default]") |
| 861 parser.add_option("--host-root", |
| 862 default="", |
| 863 help="Path to the host root [default: %default]") |
861 options, args = parser.parse_args() | 864 options, args = parser.parse_args() |
862 | 865 |
863 if not options.quiet: | 866 if not options.quiet: |
864 if options.snapshot: | 867 if options.snapshot: |
865 print "V8 logs: %s, %s, %s.ll" % (options.snapshot_log, | 868 print "V8 logs: %s, %s, %s.ll" % (options.snapshot_log, |
866 options.log, | 869 options.log, |
867 options.log) | 870 options.log) |
868 else: | 871 else: |
869 print "V8 log: %s, %s.ll (no snapshot)" % (options.log, options.log) | 872 print "V8 log: %s, %s.ll (no snapshot)" % (options.log, options.log) |
870 print "Perf trace file: %s" % options.trace | 873 print "Perf trace file: %s" % options.trace |
871 | 874 |
| 875 V8_GC_FAKE_MMAP = options.gc_fake_mmap |
| 876 HOST_ROOT = options.host_root |
| 877 if os.path.exists(options.objdump): |
| 878 disasm.OBJDUMP_BIN = options.objdump |
| 879 OBJDUMP_BIN = options.objdump |
| 880 else: |
| 881 print "Cannot find %s, falling back to default objdump" % options.objdump |
| 882 |
872 # Stats. | 883 # Stats. |
873 events = 0 | 884 events = 0 |
874 ticks = 0 | 885 ticks = 0 |
875 missed_ticks = 0 | 886 missed_ticks = 0 |
876 really_missed_ticks = 0 | 887 really_missed_ticks = 0 |
877 mmap_time = 0 | 888 mmap_time = 0 |
878 sample_time = 0 | 889 sample_time = 0 |
879 | 890 |
880 # Process the snapshot log to fill the snapshot name map. | 891 # Process the snapshot log to fill the snapshot name map. |
881 snapshot_name_map = {} | 892 snapshot_name_map = {} |
(...skipping 16 matching lines...) Expand all Loading... |
898 log_reader.ReadUpToGC() | 909 log_reader.ReadUpToGC() |
899 trace_reader = TraceReader(options.trace) | 910 trace_reader = TraceReader(options.trace) |
900 while True: | 911 while True: |
901 header, offset = trace_reader.ReadEventHeader() | 912 header, offset = trace_reader.ReadEventHeader() |
902 if not header: | 913 if not header: |
903 break | 914 break |
904 events += 1 | 915 events += 1 |
905 if header.type == PERF_RECORD_MMAP: | 916 if header.type == PERF_RECORD_MMAP: |
906 start = time.time() | 917 start = time.time() |
907 mmap_info = trace_reader.ReadMmap(header, offset) | 918 mmap_info = trace_reader.ReadMmap(header, offset) |
908 if mmap_info.filename == V8_GC_FAKE_MMAP: | 919 if mmap_info.filename == HOST_ROOT + V8_GC_FAKE_MMAP: |
909 log_reader.ReadUpToGC() | 920 log_reader.ReadUpToGC() |
910 else: | 921 else: |
911 library_repo.Load(mmap_info, code_map, options) | 922 library_repo.Load(mmap_info, code_map, options) |
912 mmap_time += time.time() - start | 923 mmap_time += time.time() - start |
913 elif header.type == PERF_RECORD_SAMPLE: | 924 elif header.type == PERF_RECORD_SAMPLE: |
914 ticks += 1 | 925 ticks += 1 |
915 start = time.time() | 926 start = time.time() |
916 sample = trace_reader.ReadSample(header, offset) | 927 sample = trace_reader.ReadSample(header, offset) |
917 code = code_map.Find(sample.ip) | 928 code = code_map.Find(sample.ip) |
918 if code: | 929 if code: |
(...skipping 23 matching lines...) Expand all Loading... |
942 print "%10d total ticks" % ticks | 953 print "%10d total ticks" % ticks |
943 print "%10d ticks not in symbols" % missed_ticks | 954 print "%10d ticks not in symbols" % missed_ticks |
944 print "%10d unaccounted ticks" % really_missed_ticks | 955 print "%10d unaccounted ticks" % really_missed_ticks |
945 print "%10d total symbols" % len([c for c in code_map.AllCode()]) | 956 print "%10d total symbols" % len([c for c in code_map.AllCode()]) |
946 print "%10d used symbols" % len([c for c in code_map.UsedCode()]) | 957 print "%10d used symbols" % len([c for c in code_map.UsedCode()]) |
947 print "%9.2fs library processing time" % mmap_time | 958 print "%9.2fs library processing time" % mmap_time |
948 print "%9.2fs tick processing time" % sample_time | 959 print "%9.2fs tick processing time" % sample_time |
949 | 960 |
950 log_reader.Dispose() | 961 log_reader.Dispose() |
951 trace_reader.Dispose() | 962 trace_reader.Dispose() |
OLD | NEW |