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.
8 from lib
.symbol
import FUNCTION_SYMBOLS
, SOURCEFILE_SYMBOLS
, TYPEINFO_SYMBOLS
11 LOGGER
= logging
.getLogger('dmprof')
13 # Indexes in dumped heap profile dumps.
14 VIRTUAL
, COMMITTED
, ALLOC_COUNT
, FREE_COUNT
, _
, BUCKET_ID
= range(6)
18 """Represents a bucket, which is a unit of memory block classification."""
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
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
32 self
.component_cache
= ''
36 result
.append(self
._allocator
_type
)
37 if self
._symbolized
_typeinfo
== 'no typeinfo':
38 result
.append('tno_typeinfo')
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
)
48 def symbolize(self
, symbol_mapping_cache
):
49 """Makes a symbolized stacktrace and typeinfo with |symbol_mapping_cache|.
52 symbol_mapping_cache: A SymbolMappingCache object.
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'
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'
73 def clear_component_cache(self
):
74 self
.component_cache
= ''
78 return self
._stacktrace
81 def allocator_type(self
):
82 return self
._allocator
_type
89 def typeinfo_name(self
):
90 return self
._typeinfo
_name
93 def symbolized_stackfunction(self
):
94 return self
._symbolized
_stackfunction
97 def symbolized_joined_stackfunction(self
):
98 return self
._symbolized
_joined
_stackfunction
101 def symbolized_stacksourcefile(self
):
102 return self
._symbolized
_stacksourcefile
105 def symbolized_joined_stacksourcefile(self
):
106 return self
._symbolized
_joined
_stacksourcefile
109 def symbolized_typeinfo(self
):
110 return self
._symbolized
_typeinfo
113 class BucketSet(object):
114 """Represents a set of bucket."""
117 self
._code
_addresses
= set()
118 self
._typeinfo
_addresses
= set()
120 def load(self
, prefix
):
121 """Loads all related bucket files.
124 prefix: A prefix string for bucket file names.
126 LOGGER
.info('Loading bucket files.')
131 path
= '%s.%04d.buckets' % (prefix
, n
)
132 if not os
.path
.exists(path
) or not os
.stat(path
).st_size
:
138 LOGGER
.info(' %s' % path
)
139 with
open(path
, 'r') as f
:
144 def _load_file(self
, bucket_f
):
145 for line
in bucket_f
:
150 for index
, word
in enumerate(words
):
154 typeinfo
= int(word
[1:], 16)
155 self
._typeinfo
_addresses
.add(typeinfo
)
157 typeinfo_name
= word
[1:]
159 stacktrace_begin
= index
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
)
168 for bucket_id
, bucket_content
in self
._buckets
.iteritems():
169 yield bucket_id
, bucket_content
171 def __getitem__(self
, bucket_id
):
172 return self
._buckets
[bucket_id
]
174 def get(self
, bucket_id
):
175 return self
._buckets
.get(bucket_id
)
177 def symbolize(self
, symbol_mapping_cache
):
178 for bucket_content
in self
._buckets
.itervalues():
179 bucket_content
.symbolize(symbol_mapping_cache
)
181 def clear_component_cache(self
):
182 for bucket_content
in self
._buckets
.itervalues():
183 bucket_content
.clear_component_cache()
185 def iter_addresses(self
, symbol_type
):
186 if symbol_type
in [FUNCTION_SYMBOLS
, SOURCEFILE_SYMBOLS
]:
187 for function
in self
._code
_addresses
:
190 for function
in self
._typeinfo
_addresses
: