OLD | NEW |
(Empty) | |
| 1 # Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 import logging |
| 6 import os |
| 7 |
| 8 from lib.symbol import FUNCTION_SYMBOLS, SOURCEFILE_SYMBOLS, TYPEINFO_SYMBOLS |
| 9 |
| 10 |
| 11 LOGGER = logging.getLogger('dmprof') |
| 12 |
| 13 # Indexes in dumped heap profile dumps. |
| 14 VIRTUAL, COMMITTED, ALLOC_COUNT, FREE_COUNT, _, BUCKET_ID = range(6) |
| 15 |
| 16 |
| 17 class Bucket(object): |
| 18 """Represents a bucket, which is a unit of memory block classification.""" |
| 19 |
| 20 def __init__(self, stacktrace, allocator_type, typeinfo, typeinfo_name): |
| 21 self._stacktrace = stacktrace |
| 22 self._allocator_type = allocator_type |
| 23 self._typeinfo = typeinfo |
| 24 self._typeinfo_name = typeinfo_name |
| 25 |
| 26 self._symbolized_stackfunction = stacktrace |
| 27 self._symbolized_joined_stackfunction = '' |
| 28 self._symbolized_stacksourcefile = stacktrace |
| 29 self._symbolized_joined_stacksourcefile = '' |
| 30 self._symbolized_typeinfo = typeinfo_name |
| 31 |
| 32 self.component_cache = '' |
| 33 |
| 34 def __str__(self): |
| 35 result = [] |
| 36 result.append(self._allocator_type) |
| 37 if self._symbolized_typeinfo == 'no typeinfo': |
| 38 result.append('tno_typeinfo') |
| 39 else: |
| 40 result.append('t' + self._symbolized_typeinfo) |
| 41 result.append('n' + self._typeinfo_name) |
| 42 result.extend(['%s(@%s)' % (function, sourcefile) |
| 43 for function, sourcefile |
| 44 in zip(self._symbolized_stackfunction, |
| 45 self._symbolized_stacksourcefile)]) |
| 46 return ' '.join(result) |
| 47 |
| 48 def symbolize(self, symbol_mapping_cache): |
| 49 """Makes a symbolized stacktrace and typeinfo with |symbol_mapping_cache|. |
| 50 |
| 51 Args: |
| 52 symbol_mapping_cache: A SymbolMappingCache object. |
| 53 """ |
| 54 # TODO(dmikurube): Fill explicitly with numbers if symbol not found. |
| 55 self._symbolized_stackfunction = [ |
| 56 symbol_mapping_cache.lookup(FUNCTION_SYMBOLS, address) |
| 57 for address in self._stacktrace] |
| 58 self._symbolized_joined_stackfunction = ' '.join( |
| 59 self._symbolized_stackfunction) |
| 60 self._symbolized_stacksourcefile = [ |
| 61 symbol_mapping_cache.lookup(SOURCEFILE_SYMBOLS, address) |
| 62 for address in self._stacktrace] |
| 63 self._symbolized_joined_stacksourcefile = ' '.join( |
| 64 self._symbolized_stacksourcefile) |
| 65 if not self._typeinfo: |
| 66 self._symbolized_typeinfo = 'no typeinfo' |
| 67 else: |
| 68 self._symbolized_typeinfo = symbol_mapping_cache.lookup( |
| 69 TYPEINFO_SYMBOLS, self._typeinfo) |
| 70 if not self._symbolized_typeinfo: |
| 71 self._symbolized_typeinfo = 'no typeinfo' |
| 72 |
| 73 def clear_component_cache(self): |
| 74 self.component_cache = '' |
| 75 |
| 76 @property |
| 77 def stacktrace(self): |
| 78 return self._stacktrace |
| 79 |
| 80 @property |
| 81 def allocator_type(self): |
| 82 return self._allocator_type |
| 83 |
| 84 @property |
| 85 def typeinfo(self): |
| 86 return self._typeinfo |
| 87 |
| 88 @property |
| 89 def typeinfo_name(self): |
| 90 return self._typeinfo_name |
| 91 |
| 92 @property |
| 93 def symbolized_stackfunction(self): |
| 94 return self._symbolized_stackfunction |
| 95 |
| 96 @property |
| 97 def symbolized_joined_stackfunction(self): |
| 98 return self._symbolized_joined_stackfunction |
| 99 |
| 100 @property |
| 101 def symbolized_stacksourcefile(self): |
| 102 return self._symbolized_stacksourcefile |
| 103 |
| 104 @property |
| 105 def symbolized_joined_stacksourcefile(self): |
| 106 return self._symbolized_joined_stacksourcefile |
| 107 |
| 108 @property |
| 109 def symbolized_typeinfo(self): |
| 110 return self._symbolized_typeinfo |
| 111 |
| 112 |
| 113 class BucketSet(object): |
| 114 """Represents a set of bucket.""" |
| 115 def __init__(self): |
| 116 self._buckets = {} |
| 117 self._code_addresses = set() |
| 118 self._typeinfo_addresses = set() |
| 119 |
| 120 def load(self, prefix): |
| 121 """Loads all related bucket files. |
| 122 |
| 123 Args: |
| 124 prefix: A prefix string for bucket file names. |
| 125 """ |
| 126 LOGGER.info('Loading bucket files.') |
| 127 |
| 128 n = 0 |
| 129 skipped = 0 |
| 130 while True: |
| 131 path = '%s.%04d.buckets' % (prefix, n) |
| 132 if not os.path.exists(path) or not os.stat(path).st_size: |
| 133 if skipped > 10: |
| 134 break |
| 135 n += 1 |
| 136 skipped += 1 |
| 137 continue |
| 138 LOGGER.info(' %s' % path) |
| 139 with open(path, 'r') as f: |
| 140 self._load_file(f) |
| 141 n += 1 |
| 142 skipped = 0 |
| 143 |
| 144 def _load_file(self, bucket_f): |
| 145 for line in bucket_f: |
| 146 words = line.split() |
| 147 typeinfo = None |
| 148 typeinfo_name = '' |
| 149 stacktrace_begin = 2 |
| 150 for index, word in enumerate(words): |
| 151 if index < 2: |
| 152 continue |
| 153 if word[0] == 't': |
| 154 typeinfo = int(word[1:], 16) |
| 155 self._typeinfo_addresses.add(typeinfo) |
| 156 elif word[0] == 'n': |
| 157 typeinfo_name = word[1:] |
| 158 else: |
| 159 stacktrace_begin = index |
| 160 break |
| 161 stacktrace = [int(address, 16) for address in words[stacktrace_begin:]] |
| 162 for frame in stacktrace: |
| 163 self._code_addresses.add(frame) |
| 164 self._buckets[int(words[0])] = Bucket( |
| 165 stacktrace, words[1], typeinfo, typeinfo_name) |
| 166 |
| 167 def __iter__(self): |
| 168 for bucket_id, bucket_content in self._buckets.iteritems(): |
| 169 yield bucket_id, bucket_content |
| 170 |
| 171 def __getitem__(self, bucket_id): |
| 172 return self._buckets[bucket_id] |
| 173 |
| 174 def get(self, bucket_id): |
| 175 return self._buckets.get(bucket_id) |
| 176 |
| 177 def symbolize(self, symbol_mapping_cache): |
| 178 for bucket_content in self._buckets.itervalues(): |
| 179 bucket_content.symbolize(symbol_mapping_cache) |
| 180 |
| 181 def clear_component_cache(self): |
| 182 for bucket_content in self._buckets.itervalues(): |
| 183 bucket_content.clear_component_cache() |
| 184 |
| 185 def iter_addresses(self, symbol_type): |
| 186 if symbol_type in [FUNCTION_SYMBOLS, SOURCEFILE_SYMBOLS]: |
| 187 for function in self._code_addresses: |
| 188 yield function |
| 189 else: |
| 190 for function in self._typeinfo_addresses: |
| 191 yield function |
OLD | NEW |