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
.policy
import PolicySet
9 from lib
.subcommand
import SubCommand
12 LOGGER
= logging
.getLogger('dmprof')
15 class PProfCommand(SubCommand
):
17 super(PProfCommand
, self
).__init
__(
18 'Usage: %prog pprof [-c COMPONENT] <dump> <policy>')
19 self
._parser
.add_option('-c', '--component', type='string',
21 help='restrict to COMPONENT', metavar
='COMPONENT')
23 def do(self
, sys_argv
):
24 options
, args
= self
._parse
_args
(sys_argv
, 2)
27 target_policy
= args
[2]
28 component
= options
.component
30 (bucket_set
, dump
) = SubCommand
.load_basic_files(dump_path
, False)
31 policy_set
= PolicySet
.load(SubCommand
._parse
_policy
_list
(target_policy
))
33 with
open(SubCommand
._find
_prefix
(dump_path
) + '.maps', 'r') as maps_f
:
34 maps_lines
= maps_f
.readlines()
36 dump
, policy_set
[target_policy
], bucket_set
, maps_lines
, component
,
42 def _output(dump
, policy
, bucket_set
, maps_lines
, component_name
, out
):
43 """Converts the heap profile dump so it can be processed by pprof.
47 policy: A Policy object.
48 bucket_set: A BucketSet object.
49 maps_lines: A list of strings containing /proc/.../maps.
50 component_name: A name of component for filtering.
51 out: An IO object to output.
53 out
.write('heap profile: ')
54 com_committed
, com_allocs
= PProfCommand
._accumulate
(
55 dump
, policy
, bucket_set
, component_name
)
57 out
.write('%6d: %8s [%6d: %8s] @ heapprofile\n' % (
58 com_allocs
, com_committed
, com_allocs
, com_committed
))
60 PProfCommand
._output
_stacktrace
_lines
(
61 dump
, policy
, bucket_set
, component_name
, out
)
63 out
.write('MAPPED_LIBRARIES:\n')
64 for line
in maps_lines
:
68 def _accumulate(dump
, policy
, bucket_set
, component_name
):
69 """Accumulates size of committed chunks and the number of allocated chunks.
73 policy: A Policy object.
74 bucket_set: A BucketSet object.
75 component_name: A name of component for filtering.
78 Two integers which are the accumulated size of committed regions and the
79 number of allocated chunks, respectively.
84 for _
, region
in dump
.iter_map
:
85 if region
[0] != 'hooked':
87 component_match
, bucket
= policy
.find_mmap(region
, bucket_set
)
89 if (component_name
and component_name
!= component_match
) or (
90 region
[1]['committed'] == 0):
93 com_committed
+= region
[1]['committed']
96 for bucket_id
, _
, committed
, allocs
, frees
in dump
.iter_stacktrace
:
97 bucket
= bucket_set
.get(bucket_id
)
98 if not bucket
or bucket
.allocator_type
== 'malloc':
99 component_match
= policy
.find_malloc(bucket
)
100 elif bucket
.allocator_type
== 'mmap':
105 (component_name
and component_name
!= component_match
)):
108 com_committed
+= committed
109 com_allocs
+= allocs
- frees
111 return com_committed
, com_allocs
114 def _output_stacktrace_lines(dump
, policy
, bucket_set
, component_name
, out
):
115 """Prints information of stacktrace lines for pprof.
119 policy: A Policy object.
120 bucket_set: A BucketSet object.
121 component_name: A name of component for filtering.
122 out: An IO object to output.
124 for _
, region
in dump
.iter_map
:
125 if region
[0] != 'hooked':
127 component_match
, bucket
= policy
.find_mmap(region
, bucket_set
)
129 if (component_name
and component_name
!= component_match
) or (
130 region
[1]['committed'] == 0):
133 out
.write(' 1: %8s [ 1: %8s] @' % (
134 region
[1]['committed'], region
[1]['committed']))
135 for address
in bucket
.stacktrace
:
136 out
.write(' 0x%016x' % address
)
139 for bucket_id
, _
, committed
, allocs
, frees
in dump
.iter_stacktrace
:
140 bucket
= bucket_set
.get(bucket_id
)
141 if not bucket
or bucket
.allocator_type
== 'malloc':
142 component_match
= policy
.find_malloc(bucket
)
143 elif bucket
.allocator_type
== 'mmap':
148 (component_name
and component_name
!= component_match
)):
151 out
.write('%6d: %8s [%6d: %8s] @' % (
152 allocs
- frees
, str(committed
), allocs
- frees
, str(committed
)))
153 for address
in bucket
.stacktrace
:
154 out
.write(' 0x%016x' % address
)