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

Side by Side Diff: tools/deep_memory_profiler/dmprof

Issue 10826008: Load static symbol information lazily with some clean-ups. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: refine Created 8 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | tools/find_runtime_symbols/find_runtime_symbols.py » ('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 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """The deep heap profiler script for Chrome.""" 6 """The deep heap profiler script for Chrome."""
7 7
8 from datetime import datetime 8 from datetime import datetime
9 import json 9 import json
10 import optparse 10 import optparse
11 import os 11 import os
12 import re 12 import re
13 import shutil 13 import shutil
14 import subprocess 14 import subprocess
15 import sys 15 import sys
16 import tempfile 16 import tempfile
17 17
18 FIND_RUNTIME_SYMBOLS_PATH = os.path.join( 18 FIND_RUNTIME_SYMBOLS_PATH = os.path.join(
19 os.path.dirname(os.path.abspath(__file__)), 19 os.path.dirname(os.path.abspath(__file__)),
20 os.pardir, 20 os.pardir,
21 'find_runtime_symbols') 21 'find_runtime_symbols')
22 sys.path.append(FIND_RUNTIME_SYMBOLS_PATH) 22 sys.path.append(FIND_RUNTIME_SYMBOLS_PATH)
23 23
24 from find_runtime_symbols import find_runtime_symbols_list
24 from prepare_symbol_info import prepare_symbol_info 25 from prepare_symbol_info import prepare_symbol_info
25 from find_runtime_symbols import find_runtime_symbols_list 26 from static_symbols import StaticSymbols
26 27
27 BUCKET_ID = 5 28 BUCKET_ID = 5
28 VIRTUAL = 0 29 VIRTUAL = 0
29 COMMITTED = 1 30 COMMITTED = 1
30 ALLOC_COUNT = 2 31 ALLOC_COUNT = 2
31 FREE_COUNT = 3 32 FREE_COUNT = 3
32 NULL_REGEX = re.compile('') 33 NULL_REGEX = re.compile('')
33 34
34 POLICIES_JSON_PATH = os.path.join( 35 POLICIES_JSON_PATH = os.path.join(
35 os.path.dirname(os.path.abspath(__file__)), 36 os.path.dirname(os.path.abspath(__file__)),
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 return "invalid heap profile dump: %s" % repr(self.value) 100 return "invalid heap profile dump: %s" % repr(self.value)
100 101
101 102
102 class ObsoleteDumpVersionException(ParsingException): 103 class ObsoleteDumpVersionException(ParsingException):
103 def __init__(self, value): 104 def __init__(self, value):
104 self.value = value 105 self.value = value
105 def __str__(self): 106 def __str__(self):
106 return "obsolete heap profile dump version: %s" % repr(self.value) 107 return "obsolete heap profile dump version: %s" % repr(self.value)
107 108
108 109
110 class DelayedStaticSymbols(object):
111 """Represents static symbol information loaded lazily."""
112
113 def __init__(self, prefix, keep=False):
114 self.maps_path = prefix + '.maps'
115 self.keep = keep
116 if keep:
117 self.prepared_data_dir = prefix + '.pre'
118 self.loaded_static_symbols = None
119
120 def get(self):
121 if not self.loaded_static_symbols:
122 if not self.keep:
123 self.prepared_data_dir = tempfile.mkdtemp()
124 try:
125 prepare_symbol_info(self.maps_path, self.prepared_data_dir)
126 self.loaded_static_symbols = StaticSymbols.load(self.prepared_data_dir)
127 finally:
128 if not self.keep:
129 shutil.rmtree(self.prepared_data_dir)
130 return self.loaded_static_symbols
131
132
109 class Rule(object): 133 class Rule(object):
110 """Represents one matching rule in a policy file.""" 134 """Represents one matching rule in a policy file."""
111 135
112 def __init__(self, name, mmap, pattern): 136 def __init__(self, name, mmap, pattern):
113 self.name = name 137 self.name = name
114 self.mmap = mmap 138 self.mmap = mmap
115 self.condition = re.compile(pattern + r'\Z') 139 self.condition = re.compile(pattern + r'\Z')
116 140
117 141
118 class Policy(object): 142 class Policy(object):
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 symbols: A dict mapping runtime addresses to symbol names. 209 symbols: A dict mapping runtime addresses to symbol names.
186 """ 210 """
187 for line in self.stacktrace_lines: 211 for line in self.stacktrace_lines:
188 words = line.split() 212 words = line.split()
189 bucket = buckets.get(int(words[BUCKET_ID])) 213 bucket = buckets.get(int(words[BUCKET_ID]))
190 if not bucket: 214 if not bucket:
191 continue 215 continue
192 for i in range(0, BUCKET_ID - 1): 216 for i in range(0, BUCKET_ID - 1):
193 sys.stdout.write(words[i] + ' ') 217 sys.stdout.write(words[i] + ' ')
194 for address in bucket.stacktrace: 218 for address in bucket.stacktrace:
195 sys.stdout.write((symbols.get(address) or address) + ' ') 219 sys.stdout.write((symbols.get(address) or ('0x%016x' % address)) + ' ')
196 sys.stdout.write('\n') 220 sys.stdout.write('\n')
197 221
198 @staticmethod 222 @staticmethod
199 def accumulate_size_for_pprof(stacktrace_lines, rule_list, buckets, 223 def accumulate_size_for_pprof(stacktrace_lines, rule_list, buckets,
200 component_name, symbols): 224 component_name, symbols):
201 """Accumulates size of committed chunks and the number of allocated chunks. 225 """Accumulates size of committed chunks and the number of allocated chunks.
202 226
203 Args: 227 Args:
204 stacktrace_lines: A list of strings which are valid as stacktraces. 228 stacktrace_lines: A list of strings which are valid as stacktraces.
205 rule_list: A list of Rule objects. 229 rule_list: A list of Rule objects.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 (component_name and 269 (component_name and
246 component_name != get_component(rule_list, bucket, symbols))): 270 component_name != get_component(rule_list, bucket, symbols))):
247 continue 271 continue
248 272
249 sys.stdout.write('%6d: %8s [%6d: %8s] @' % ( 273 sys.stdout.write('%6d: %8s [%6d: %8s] @' % (
250 int(words[ALLOC_COUNT]) - int(words[FREE_COUNT]), 274 int(words[ALLOC_COUNT]) - int(words[FREE_COUNT]),
251 words[COMMITTED], 275 words[COMMITTED],
252 int(words[ALLOC_COUNT]) - int(words[FREE_COUNT]), 276 int(words[ALLOC_COUNT]) - int(words[FREE_COUNT]),
253 words[COMMITTED])) 277 words[COMMITTED]))
254 for address in bucket.stacktrace: 278 for address in bucket.stacktrace:
255 sys.stdout.write(' ' + address) 279 sys.stdout.write(' 0x%016x' % address)
256 sys.stdout.write('\n') 280 sys.stdout.write('\n')
257 281
258 def print_for_pprof( 282 def print_for_pprof(
259 self, rule_list, buckets, maps_lines, component_name, symbols): 283 self, rule_list, buckets, maps_lines, component_name, symbols):
260 """Converts the heap profile dump so it can be processed by pprof. 284 """Converts the heap profile dump so it can be processed by pprof.
261 285
262 Args: 286 Args:
263 rule_list: A list of Rule objects. 287 rule_list: A list of Rule objects.
264 buckets: A dict mapping bucket ids to Bucket objects. 288 buckets: A dict mapping bucket ids to Bucket objects.
265 maps_lines: A list of strings containing /proc/.../maps. 289 maps_lines: A list of strings containing /proc/.../maps.
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 sorted_sizes_list = sorted( 593 sorted_sizes_list = sorted(
570 sizes.iteritems(), key=(lambda x: x[1]), reverse=True) 594 sizes.iteritems(), key=(lambda x: x[1]), reverse=True)
571 total = 0 595 total = 0
572 for size_pair in sorted_sizes_list: 596 for size_pair in sorted_sizes_list:
573 sys.stdout.write('%10d %s\n' % (size_pair[1], size_pair[0])) 597 sys.stdout.write('%10d %s\n' % (size_pair[1], size_pair[0]))
574 total += size_pair[1] 598 total += size_pair[1]
575 sys.stderr.write('total: %d\n' % (total)) 599 sys.stderr.write('total: %d\n' % (total))
576 600
577 601
578 def update_symbols( 602 def update_symbols(
579 symbol_path, maps_path, appeared_addresses, symbols): 603 symbol_path, delayed_static_symbols, appeared_addresses, symbols):
580 """Updates address/symbol mapping on memory and in a .symbol cache file. 604 """Updates address/symbol mapping on memory and in a .symbol cache file.
581 605
582 It reads cached address/symbol mapping from a .symbol file if it exists. 606 It reads cached address/symbol mapping from a .symbol file if it exists.
583 Then, it resolves unresolved addresses from a Chrome binary with pprof. 607 Then, it resolves unresolved addresses from a Chrome binary with pprof.
584 Both mappings on memory and in a .symbol cache file are updated. 608 Both mappings on memory and in a .symbol cache file are updated.
585 609
586 Symbol files are formatted as follows: 610 Symbol files are formatted as follows:
587 <Address> <Symbol> 611 <Address> <Symbol>
588 <Address> <Symbol> 612 <Address> <Symbol>
589 <Address> <Symbol> 613 <Address> <Symbol>
590 ... 614 ...
591 615
592 Args: 616 Args:
593 symbol_path: A string representing a path for a .symbol file. 617 symbol_path: A string representing a path for a .symbol file.
594 maps_path: A string of the path of /proc/.../maps. 618 delayed_static_symbols: A DelayedStaticSymbols object.
595 appeared_addresses: A list of known addresses. 619 appeared_addresses: A list of known addresses.
596 symbols: A dict mapping runtime addresses to symbol names. 620 symbols: A dict mapping runtime addresses to symbol names.
597 """ 621 """
598 with open(symbol_path, mode='a+') as symbol_f: 622 with open(symbol_path, mode='a+') as symbol_f:
599 symbol_lines = symbol_f.readlines() 623 symbol_lines = symbol_f.readlines()
600 if symbol_lines: 624 if symbol_lines:
601 for line in symbol_lines: 625 for line in symbol_lines:
602 items = line.split(None, 1) 626 items = line.split(None, 1)
603 if len(items) == 1: 627 if len(items) == 1:
604 items.append('??') 628 items.append('??')
605 symbols[items[0]] = items[1].rstrip() 629 symbols[int(items[0], 16)] = items[1].rstrip()
606 if symbols: 630 if symbols:
607 sys.stderr.write(' Found %d symbols in cache.\n' % len(symbols)) 631 sys.stderr.write(' Found %d symbols in cache.\n' % len(symbols))
608 else: 632 else:
609 sys.stderr.write(' No symbols found in cache.\n') 633 sys.stderr.write(' No symbols found in cache.\n')
610 634
611 unresolved_addresses = sorted( 635 unresolved_addresses = sorted(
612 a for a in appeared_addresses if a not in symbols) 636 a for a in appeared_addresses if a not in symbols)
613 637
614 if not unresolved_addresses: 638 if not unresolved_addresses:
615 sys.stderr.write(' No need to resolve any more addresses.\n') 639 sys.stderr.write(' No need to resolve any more addresses.\n')
616 else: 640 else:
617 sys.stderr.write(' %d addresses are unresolved.\n' % 641 sys.stderr.write(' %d addresses unresolved.\n' %
618 len(unresolved_addresses)) 642 len(unresolved_addresses))
619 prepared_data_dir = tempfile.mkdtemp() 643 static_symbols = delayed_static_symbols.get()
620 try: 644 symbol_list = find_runtime_symbols_list(
621 prepare_symbol_info(maps_path, prepared_data_dir) 645 static_symbols, unresolved_addresses)
622 646
623 symbol_list = find_runtime_symbols_list( 647 for address, symbol in zip(unresolved_addresses, symbol_list):
624 prepared_data_dir, unresolved_addresses) 648 if not symbol:
649 symbol = '??'
650 stripped_symbol = symbol.strip()
651 symbols[address] = stripped_symbol
652 symbol_f.write('%x %s\n' % (address, stripped_symbol))
625 653
626 for address, symbol in zip(unresolved_addresses, symbol_list): 654 sys.stderr.write(' All symbols resolved.\n')
627 if not symbol:
628 symbol = '??'
629 stripped_symbol = symbol.strip()
630 symbols[address] = stripped_symbol
631 symbol_f.write('%s %s\n' % (address, stripped_symbol))
632 finally:
633 shutil.rmtree(prepared_data_dir)
634 655
635 656
636 def parse_policy(policy_path): 657 def parse_policy(policy_path):
637 """Parses policy file. 658 """Parses policy file.
638 659
639 A policy file contains component's names and their 660 A policy file contains component's names and their
640 stacktrace pattern written in regular expression. 661 stacktrace pattern written in regular expression.
641 Those patterns are matched against each symbols of 662 Those patterns are matched against each symbols of
642 each stacktraces in the order written in the policy file 663 each stacktraces in the order written in the policy file
643 664
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
697 buckets_path = '%s.%04d.buckets' % (prefix, n) 718 buckets_path = '%s.%04d.buckets' % (prefix, n)
698 if not os.path.exists(buckets_path): 719 if not os.path.exists(buckets_path):
699 if n > 10: 720 if n > 10:
700 break 721 break
701 n += 1 722 n += 1
702 continue 723 continue
703 sys.stderr.write(' %s\n' % buckets_path) 724 sys.stderr.write(' %s\n' % buckets_path)
704 with open(buckets_path, 'r') as buckets_f: 725 with open(buckets_path, 'r') as buckets_f:
705 for line in buckets_f: 726 for line in buckets_f:
706 words = line.split() 727 words = line.split()
707 buckets[int(words[0])] = Bucket(words[2:], words[1] == 'mmap') 728 stacktrace = [int(address, 16) for address in words[2:]]
729 buckets[int(words[0])] = Bucket(stacktrace, words[1] == 'mmap')
708 n += 1 730 n += 1
709 731
710 return buckets 732 return buckets
711 733
712 734
713 def determine_dump_path_list(dump_path, prefix): 735 def determine_dump_path_list(dump_path, prefix):
714 dump_path_list = [dump_path] 736 dump_path_list = [dump_path]
715 737
716 # search for the sequence of files 738 # search for the sequence of files
717 n = int(dump_path[len(dump_path) - 9 : len(dump_path) - 5]) 739 n = int(dump_path[len(dump_path) - 9 : len(dump_path) - 5])
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
754 sys.stderr.write('Loading heap dump files.\n') 776 sys.stderr.write('Loading heap dump files.\n')
755 appeared_addresses = set() 777 appeared_addresses = set()
756 dumps = [] 778 dumps = []
757 for path in dump_path_list: 779 for path in dump_path_list:
758 sys.stderr.write(' %s' % path) 780 sys.stderr.write(' %s' % path)
759 dumps.append(load_single_dump(path, buckets, appeared_addresses)) 781 dumps.append(load_single_dump(path, buckets, appeared_addresses))
760 sys.stderr.write('\n') 782 sys.stderr.write('\n')
761 return dumps, appeared_addresses 783 return dumps, appeared_addresses
762 784
763 785
764 def load_and_update_symbol_cache(prefix, appeared_addresses): 786 def load_and_update_symbol_cache(
765 maps_path = prefix + '.maps' 787 prefix, appeared_addresses, delayed_static_symbols):
766 symbol_path = prefix + '.symbols' 788 symbol_path = prefix + '.symbols'
767 sys.stderr.write('Loading and updating symbol cache: "%s".\n' % symbol_path) 789 sys.stderr.write('Loading and updating symbol cache: "%s".\n' % symbol_path)
768 symbols = {} 790 symbols = {}
769 update_symbols(symbol_path, maps_path, appeared_addresses, symbols) 791 update_symbols(
792 symbol_path, delayed_static_symbols, appeared_addresses, symbols)
770 return symbols 793 return symbols
771 794
772 795
773 def load_default_policies(): 796 def load_default_policies():
774 with open(POLICIES_JSON_PATH, mode='r') as policies_f: 797 with open(POLICIES_JSON_PATH, mode='r') as policies_f:
775 default_policies = json.load(policies_f) 798 default_policies = json.load(policies_f)
776 return default_policies 799 return default_policies
777 800
778 801
779 def load_policy(policies_dict, policy_label): 802 def load_policy(policies_dict, policy_label):
(...skipping 21 matching lines...) Expand all
801 for specified_policy in policy_labels: 824 for specified_policy in policy_labels:
802 if specified_policy in default_policies: 825 if specified_policy in default_policies:
803 specified_policies[specified_policy] = ( 826 specified_policies[specified_policy] = (
804 default_policies[specified_policy]) 827 default_policies[specified_policy])
805 policies = load_policies_dict(specified_policies) 828 policies = load_policies_dict(specified_policies)
806 else: 829 else:
807 policies = load_policies_dict(default_policies) 830 policies = load_policies_dict(default_policies)
808 return policies 831 return policies
809 832
810 833
834 def load_basic_files_with_multiple_dumps(dump_path, keep):
835 prefix = find_prefix(dump_path)
836 buckets = load_buckets(prefix)
837 dumps, appeared_addresses = load_dumps(
838 determine_dump_path_list(dump_path, prefix), buckets)
839 delayed_static_symbols = DelayedStaticSymbols(prefix, keep)
840 symbols = load_and_update_symbol_cache(
841 prefix, appeared_addresses, delayed_static_symbols)
842 return buckets, dumps, appeared_addresses, delayed_static_symbols, symbols
843
844
845 def load_basic_files_with_single_dump(dump_path, keep):
846 prefix = find_prefix(dump_path)
847 buckets = load_buckets(prefix)
848 dump, appeared_addresses = load_dump(dump_path, buckets)
849 delayed_static_symbols = DelayedStaticSymbols(prefix, keep)
850 symbols = load_and_update_symbol_cache(
851 prefix, appeared_addresses, delayed_static_symbols)
852 return buckets, dump, appeared_addresses, delayed_static_symbols, symbols
853
854
811 def do_stacktrace(sys_argv): 855 def do_stacktrace(sys_argv):
812 parser = optparse.OptionParser(usage='Usage: %prog stacktrace <dump>') 856 parser = optparse.OptionParser(
857 'Usage: %prog stacktrace [--keep] <dump>')
858 parser.add_option('--keep', dest='keep', action='store_true')
813 options, args = parser.parse_args(sys_argv) 859 options, args = parser.parse_args(sys_argv)
814 860
815 if len(args) != 2: 861 if len(args) != 2:
816 parser.error('needs 1 argument.') 862 parser.error('needs 1 argument.')
817 return 1 863 return 1
818 864
819 dump_path = args[1] 865 dump_path = args[1]
820 866
821 prefix = find_prefix(dump_path) 867 buckets, dump, appeared_addresses, delayed_static_symbols, symbols = (
822 buckets = load_buckets(prefix) 868 load_basic_files_with_single_dump(dump_path, options.keep))
823 dump, appeared_addresses = load_dump(dump_path, buckets)
824 symbols = load_and_update_symbol_cache(prefix, appeared_addresses)
825 869
826 dump.print_stacktrace(buckets, symbols) 870 dump.print_stacktrace(buckets, symbols)
827 871
828 return 0 872 return 0
829 873
830 874
831 def do_csv(sys_argv): 875 def do_csv(sys_argv):
832 parser = optparse.OptionParser('Usage: %prog csv [-p POLICY] <first-dump>') 876 parser = optparse.OptionParser(
877 'Usage: %prog csv [-p POLICY] [--keep] <first-dump>')
833 parser.add_option('-p', '--policy', type='string', dest='policy', 878 parser.add_option('-p', '--policy', type='string', dest='policy',
834 help='profile with POLICY', metavar='POLICY') 879 help='profile with POLICY', metavar='POLICY')
880 parser.add_option('--keep', dest='keep', action='store_true')
835 options, args = parser.parse_args(sys_argv) 881 options, args = parser.parse_args(sys_argv)
836 882
837 if len(args) != 2: 883 if len(args) != 2:
838 parser.error('needs 1 argument.') 884 parser.error('needs 1 argument.')
839 return 1 885 return 1
840 886
841 dump_path = args[1] 887 dump_path = args[1]
842 888
843 prefix = find_prefix(dump_path) 889 buckets, dumps, appeared_addresses, delayed_static_symbols, symbols = (
844 buckets = load_buckets(prefix) 890 load_basic_files_with_multiple_dumps(dump_path, options.keep))
845 dumps, appeared_addresses = load_dumps(
846 determine_dump_path_list(dump_path, prefix), buckets)
847 symbols = load_and_update_symbol_cache(prefix, appeared_addresses)
848 policies = load_policies(options.policy) 891 policies = load_policies(options.policy)
849 892
850 max_components = 0 893 max_components = 0
851 for policy in policies: 894 for policy in policies:
852 max_components = max(max_components, len(policies[policy].components)) 895 max_components = max(max_components, len(policies[policy].components))
853 896
854 for policy in sorted(policies): 897 for policy in sorted(policies):
855 rule_list = policies[policy].rules 898 rule_list = policies[policy].rules
856 components = policies[policy].components 899 components = policies[policy].components
857 900
(...skipping 14 matching lines...) Expand all
872 sys.stdout.write('%s%s\n' % ( 915 sys.stdout.write('%s%s\n' % (
873 ','.join(s), ',' * (max_components - len(components)))) 916 ','.join(s), ',' * (max_components - len(components))))
874 917
875 for bucket in buckets.itervalues(): 918 for bucket in buckets.itervalues():
876 bucket.clear_component_cache() 919 bucket.clear_component_cache()
877 920
878 return 0 921 return 0
879 922
880 923
881 def do_json(sys_argv): 924 def do_json(sys_argv):
882 parser = optparse.OptionParser('Usage: %prog json [-p POLICY] <first-dump>') 925 parser = optparse.OptionParser(
926 'Usage: %prog json [-p POLICY] [--keep] <first-dump>')
883 parser.add_option('-p', '--policy', type='string', dest='policy', 927 parser.add_option('-p', '--policy', type='string', dest='policy',
884 help='profile with POLICY', metavar='POLICY') 928 help='profile with POLICY', metavar='POLICY')
929 parser.add_option('--keep', dest='keep', action='store_true')
885 options, args = parser.parse_args(sys_argv) 930 options, args = parser.parse_args(sys_argv)
886 931
887 if len(args) != 2: 932 if len(args) != 2:
888 parser.error('needs 1 argument.') 933 parser.error('needs 1 argument.')
889 return 1 934 return 1
890 935
891 dump_path = args[1] 936 dump_path = args[1]
892 937
893 prefix = find_prefix(dump_path) 938 buckets, dumps, appeared_addresses, delayed_static_symbols, symbols = (
894 buckets = load_buckets(prefix) 939 load_basic_files_with_multiple_dumps(dump_path, options.keep))
895 dumps, appeared_addresses = load_dumps(
896 determine_dump_path_list(dump_path, prefix), buckets)
897 symbols = load_and_update_symbol_cache(prefix, appeared_addresses)
898 policies = load_policies(options.policy) 940 policies = load_policies(options.policy)
899 941
900 json_base = { 942 json_base = {
901 'version': 'JSON_DEEP_2', 943 'version': 'JSON_DEEP_2',
902 'policies': {}, 944 'policies': {},
903 } 945 }
904 946
905 for policy in sorted(policies): 947 for policy in sorted(policies):
906 rule_list = policies[policy].rules 948 rule_list = policies[policy].rules
907 components = policies[policy].components 949 components = policies[policy].components
(...skipping 13 matching lines...) Expand all
921 963
922 for bucket in buckets.itervalues(): 964 for bucket in buckets.itervalues():
923 bucket.clear_component_cache() 965 bucket.clear_component_cache()
924 966
925 json.dump(json_base, sys.stdout, indent=2, sort_keys=True) 967 json.dump(json_base, sys.stdout, indent=2, sort_keys=True)
926 968
927 return 0 969 return 0
928 970
929 971
930 def do_list(sys_argv): 972 def do_list(sys_argv):
931 parser = optparse.OptionParser('Usage: %prog [-p POLICY] list <first-dump>') 973 parser = optparse.OptionParser(
974 'Usage: %prog [-p POLICY] [--keep] list <first-dump>')
932 parser.add_option('-p', '--policy', type='string', dest='policy', 975 parser.add_option('-p', '--policy', type='string', dest='policy',
933 help='profile with POLICY', metavar='POLICY') 976 help='profile with POLICY', metavar='POLICY')
977 parser.add_option('--keep', dest='keep', action='store_true')
934 options, args = parser.parse_args(sys_argv) 978 options, args = parser.parse_args(sys_argv)
935 979
936 if len(args) != 2: 980 if len(args) != 2:
937 parser.error('needs 1 argument.') 981 parser.error('needs 1 argument.')
938 return 1 982 return 1
939 983
940 dump_path = args[1] 984 dump_path = args[1]
941 985
942 prefix = find_prefix(dump_path) 986 buckets, dumps, appeared_addresses, delayed_static_symbols, symbols = (
943 buckets = load_buckets(prefix) 987 load_basic_files_with_multiple_dumps(dump_path, options.keep))
944 dumps, appeared_addresses = load_dumps(
945 determine_dump_path_list(dump_path, prefix), buckets)
946 symbols = load_and_update_symbol_cache(prefix, appeared_addresses)
947 policies = load_policies(options.policy) 988 policies = load_policies(options.policy)
948 989
949 for policy in sorted(policies): 990 for policy in sorted(policies):
950 rule_list = policies[policy].rules 991 rule_list = policies[policy].rules
951 components = policies[policy].components 992 components = policies[policy].components
952 993
953 component_sizes = dumps[0].apply_policy( 994 component_sizes = dumps[0].apply_policy(
954 rule_list, buckets, dumps[0].dump_time, components, symbols) 995 rule_list, buckets, dumps[0].dump_time, components, symbols)
955 sys.stdout.write('%s:\n' % policy) 996 sys.stdout.write('%s:\n' % policy)
956 for c in components: 997 for c in components:
957 if c in ['hour', 'minute', 'second']: 998 if c in ['hour', 'minute', 'second']:
958 sys.stdout.write('%30s %10.3f\n' % (c, component_sizes[c])) 999 sys.stdout.write('%30s %10.3f\n' % (c, component_sizes[c]))
959 else: 1000 else:
960 sys.stdout.write('%30s %10.3f\n' % ( 1001 sys.stdout.write('%30s %10.3f\n' % (
961 c, component_sizes[c] / 1024.0 / 1024.0)) 1002 c, component_sizes[c] / 1024.0 / 1024.0))
962 1003
963 for bucket in buckets.itervalues(): 1004 for bucket in buckets.itervalues():
964 bucket.clear_component_cache() 1005 bucket.clear_component_cache()
965 1006
966 return 0 1007 return 0
967 1008
968 1009
969 def do_expand(sys_argv): 1010 def do_expand(sys_argv):
970 parser = optparse.OptionParser( 1011 parser = optparse.OptionParser(
971 'Usage: %prog expand <dump> <policy> <component> <depth>') 1012 'Usage: %prog expand [--keep] <dump> <policy> <component> <depth>')
1013 parser.add_option('--keep', dest='keep', action='store_true')
972 options, args = parser.parse_args(sys_argv) 1014 options, args = parser.parse_args(sys_argv)
973 1015
974 if len(args) != 5: 1016 if len(args) != 5:
975 parser.error('needs 4 arguments.') 1017 parser.error('needs 4 arguments.')
976 return 1 1018 return 1
977 1019
978 dump_path = args[1] 1020 dump_path = args[1]
979 target_policy = args[2] 1021 target_policy = args[2]
980 component_name = args[3] 1022 component_name = args[3]
981 depth = args[4] 1023 depth = args[4]
982 1024
983 prefix = find_prefix(dump_path) 1025 buckets, dump, appeared_addresses, delayed_static_symbols, symbols = (
984 buckets = load_buckets(prefix) 1026 load_basic_files_with_single_dump(dump_path, options.keep))
985 dump, appeared_addresses = load_dump(dump_path, buckets)
986 symbols = load_and_update_symbol_cache(prefix, appeared_addresses)
987 policies = load_policies(target_policy) 1027 policies = load_policies(target_policy)
988 1028
989 rule_list = policies[target_policy].rules 1029 rule_list = policies[target_policy].rules
990 1030
991 dump.expand(rule_list, buckets, component_name, int(depth), symbols) 1031 dump.expand(rule_list, buckets, component_name, int(depth), symbols)
992 1032
993 return 0 1033 return 0
994 1034
995 1035
996 def do_pprof(sys_argv): 1036 def do_pprof(sys_argv):
997 parser = optparse.OptionParser( 1037 parser = optparse.OptionParser(
998 'Usage: %prog pprof [-c COMPONENT] <dump> <policy>') 1038 'Usage: %prog pprof [-c COMPONENT] [--keep] <dump> <policy>')
999 parser.add_option('-c', '--component', type='string', dest='component', 1039 parser.add_option('-c', '--component', type='string', dest='component',
1000 help='restrict to COMPONENT', metavar='COMPONENT') 1040 help='restrict to COMPONENT', metavar='COMPONENT')
1041 parser.add_option('--keep', dest='keep', action='store_true')
1001 options, args = parser.parse_args(sys_argv) 1042 options, args = parser.parse_args(sys_argv)
1002 1043
1003 if len(args) != 3: 1044 if len(args) != 3:
1004 parser.error('needs 2 arguments.') 1045 parser.error('needs 2 arguments.')
1005 return 1 1046 return 1
1006 1047
1007 dump_path = args[1] 1048 dump_path = args[1]
1008 target_policy = args[2] 1049 target_policy = args[2]
1009 component = options.component 1050 component = options.component
1010 1051
1011 prefix = find_prefix(dump_path) 1052 buckets, dump, appeared_addresses, delayed_static_symbols, symbols = (
1012 buckets = load_buckets(prefix) 1053 load_basic_files_with_single_dump(dump_path, options.keep))
1013 dump, appeared_addresses = load_dump(dump_path, buckets)
1014 symbols = load_and_update_symbol_cache(prefix, appeared_addresses)
1015 policies = load_policies(target_policy) 1054 policies = load_policies(target_policy)
1016 1055
1017 rule_list = policies[target_policy].rules 1056 rule_list = policies[target_policy].rules
1018 1057
1019 with open(prefix + '.maps', 'r') as maps_f: 1058 with open(find_prefix(dump_path) + '.maps', 'r') as maps_f:
1020 maps_lines = maps_f.readlines() 1059 maps_lines = maps_f.readlines()
1021 dump.print_for_pprof(rule_list, buckets, maps_lines, component, symbols) 1060 dump.print_for_pprof(rule_list, buckets, maps_lines, component, symbols)
1022 1061
1023 return 0 1062 return 0
1024 1063
1025 1064
1026 def main(): 1065 def main():
1027 COMMANDS = { 1066 COMMANDS = {
1028 'csv': do_csv, 1067 'csv': do_csv,
1029 'expand': do_expand, 1068 'expand': do_expand,
(...skipping 18 matching lines...) Expand all
1048 1087
1049 Commands: 1088 Commands:
1050 csv Classify memory usage in CSV 1089 csv Classify memory usage in CSV
1051 expand Show all stacktraces contained in the specified component 1090 expand Show all stacktraces contained in the specified component
1052 json Classify memory usage in JSON 1091 json Classify memory usage in JSON
1053 list Classify memory usage in simple listing format 1092 list Classify memory usage in simple listing format
1054 pprof Format the profile dump so that it can be processed by pprof 1093 pprof Format the profile dump so that it can be processed by pprof
1055 stacktrace Convert runtime addresses to symbol names 1094 stacktrace Convert runtime addresses to symbol names
1056 1095
1057 Quick Reference: 1096 Quick Reference:
1058 dmprof csv [-p POLICY] <first-dump> 1097 dmprof csv [-p POLICY] [--keep] <first-dump>
1059 dmprof expand <dump> <policy> <component> <depth> 1098 dmprof expand [--keep] <dump> <policy> <component> <depth>
1060 dmprof json [-p POLICY] <first-dump> 1099 dmprof json [-p POLICY] [--keep] <first-dump>
1061 dmprof list [-p POLICY] <first-dump> 1100 dmprof list [-p POLICY] [--keep] <first-dump>
1062 dmprof pprof [-c COMPONENT] <dump> <policy> 1101 dmprof pprof [-c COMPONENT] [--keep] <dump> <policy>
1063 dmprof stacktrace <dump> 1102 dmprof stacktrace [--keep] <dump>
1064 """ % (sys.argv[0])) 1103 """ % (sys.argv[0]))
1065 sys.exit(1) 1104 sys.exit(1)
1066 action = sys.argv.pop(1) 1105 action = sys.argv.pop(1)
1067 1106
1068 return COMMANDS[action](sys.argv) 1107 return COMMANDS[action](sys.argv)
1069 1108
1070 1109
1071 if __name__ == '__main__': 1110 if __name__ == '__main__':
1072 sys.exit(main()) 1111 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | tools/find_runtime_symbols/find_runtime_symbols.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698