OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright 2009 the V8 project authors. All rights reserved. | 3 # Copyright 2009 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 22 matching lines...) Expand all Loading... |
33 | 33 |
34 # Sample usage: | 34 # Sample usage: |
35 # $ ./shell --log-gc script.js | 35 # $ ./shell --log-gc script.js |
36 # $ tools/process-heap-prof.py v8.log | hp2ps -c > script-heap-graph.ps | 36 # $ tools/process-heap-prof.py v8.log | hp2ps -c > script-heap-graph.ps |
37 # ('-c' enables color, see hp2ps manual page for more options) | 37 # ('-c' enables color, see hp2ps manual page for more options) |
38 # or | 38 # or |
39 # $ tools/process-heap-prof.py --js-cons-profile v8.log | hp2ps -c > script-heap
-graph.ps | 39 # $ tools/process-heap-prof.py --js-cons-profile v8.log | hp2ps -c > script-heap
-graph.ps |
40 # to get JS constructor profile | 40 # to get JS constructor profile |
41 | 41 |
42 | 42 |
43 import csv, sys, time | 43 import csv, sys, time, optparse |
44 | 44 |
45 def process_logfile(filename, itemname): | 45 def ProcessLogFile(filename, options): |
| 46 if options.js_cons_profile: |
| 47 itemname = 'heap-js-cons-item' |
| 48 else: |
| 49 itemname = 'heap-sample-item' |
| 50 |
46 first_call_time = None | 51 first_call_time = None |
47 sample_time = 0.0 | 52 sample_time = 0.0 |
48 sampling = False | 53 sampling = False |
49 try: | 54 try: |
50 logfile = open(filename, 'rb') | 55 logfile = open(filename, 'rb') |
51 try: | 56 try: |
52 logreader = csv.reader(logfile) | 57 logreader = csv.reader(logfile) |
53 | 58 |
54 print('JOB "v8"') | 59 print('JOB "v8"') |
55 print('DATE "%s"' % time.asctime(time.localtime())) | 60 print('DATE "%s"' % time.asctime(time.localtime())) |
56 print('SAMPLE_UNIT "seconds"') | 61 print('SAMPLE_UNIT "seconds"') |
57 print('VALUE_UNIT "bytes"') | 62 print('VALUE_UNIT "bytes"') |
58 | 63 |
59 for row in logreader: | 64 for row in logreader: |
60 if row[0] == 'heap-sample-begin' and row[1] == 'Heap': | 65 if row[0] == 'heap-sample-begin' and row[1] == 'Heap': |
61 sample_time = float(row[3])/1000.0 | 66 sample_time = float(row[3])/1000.0 |
62 if first_call_time == None: | 67 if first_call_time == None: |
63 first_call_time = sample_time | 68 first_call_time = sample_time |
64 sample_time -= first_call_time | 69 sample_time -= first_call_time |
65 print('BEGIN_SAMPLE %.2f' % sample_time) | 70 print('BEGIN_SAMPLE %.2f' % sample_time) |
66 sampling = True | 71 sampling = True |
67 elif row[0] == 'heap-sample-end' and row[1] == 'Heap': | 72 elif row[0] == 'heap-sample-end' and row[1] == 'Heap': |
68 print('END_SAMPLE %.2f' % sample_time) | 73 print('END_SAMPLE %.2f' % sample_time) |
69 sampling = False | 74 sampling = False |
70 elif row[0] == itemname and sampling: | 75 elif row[0] == itemname and sampling: |
71 print('%s %d' % (row[1], int(row[3]))) | 76 print(row[1]), |
| 77 if options.count: |
| 78 print('%d' % (int(row[2]))), |
| 79 if options.size: |
| 80 print('%d' % (int(row[3]))), |
| 81 print |
72 finally: | 82 finally: |
73 logfile.close() | 83 logfile.close() |
74 except: | 84 except: |
75 sys.exit('can\'t open %s' % filename) | 85 sys.exit('can\'t open %s' % filename) |
76 | 86 |
77 if sys.argv[1] == '--js-cons-profile': | 87 |
78 process_logfile(sys.argv[2], 'heap-js-cons-item') | 88 def BuildOptions(): |
79 else: | 89 result = optparse.OptionParser() |
80 process_logfile(sys.argv[1], 'heap-sample-item') | 90 result.add_option("--js_cons_profile", help="Constructor profile", |
| 91 default=False, action="store_true") |
| 92 result.add_option("--size", help="Report object size", |
| 93 default=False, action="store_true") |
| 94 result.add_option("--count", help="Report object count", |
| 95 default=False, action="store_true") |
| 96 return result |
| 97 |
| 98 |
| 99 def ProcessOptions(options): |
| 100 if not options.size and not options.count: |
| 101 options.size = True |
| 102 return True |
| 103 |
| 104 |
| 105 def Main(): |
| 106 parser = BuildOptions() |
| 107 (options, args) = parser.parse_args() |
| 108 if not ProcessOptions(options): |
| 109 parser.print_help() |
| 110 sys.exit(); |
| 111 |
| 112 if not args: |
| 113 print "Missing logfile" |
| 114 sys.exit(); |
| 115 |
| 116 ProcessLogFile(args[0], options) |
| 117 |
| 118 |
| 119 if __name__ == '__main__': |
| 120 sys.exit(Main()) |
OLD | NEW |