Make the position of 'n files selected' label synced with the width of navigation...
[chromium-blink-merge.git] / tools / deep_memory_profiler / subcommands / pprof.py
blobecd494742d1cfc9b0ec354393f12a89800ed05ee
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.
5 import logging
6 import sys
8 from lib.policy import PolicySet
9 from lib.subcommand import SubCommand
12 LOGGER = logging.getLogger('dmprof')
15 class PProfCommand(SubCommand):
16 def __init__(self):
17 super(PProfCommand, self).__init__(
18 'Usage: %prog pprof [-c COMPONENT] <dump> <policy>')
19 self._parser.add_option('-c', '--component', type='string',
20 dest='component',
21 help='restrict to COMPONENT', metavar='COMPONENT')
23 def do(self, sys_argv):
24 options, args = self._parse_args(sys_argv, 2)
26 dump_path = args[1]
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()
35 PProfCommand._output(
36 dump, policy_set[target_policy], bucket_set, maps_lines, component,
37 sys.stdout)
39 return 0
41 @staticmethod
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.
45 Args:
46 dump: A Dump object.
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.
52 """
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:
65 out.write(line)
67 @staticmethod
68 def _accumulate(dump, policy, bucket_set, component_name):
69 """Accumulates size of committed chunks and the number of allocated chunks.
71 Args:
72 dump: A Dump object.
73 policy: A Policy object.
74 bucket_set: A BucketSet object.
75 component_name: A name of component for filtering.
77 Returns:
78 Two integers which are the accumulated size of committed regions and the
79 number of allocated chunks, respectively.
80 """
81 com_committed = 0
82 com_allocs = 0
84 for _, region in dump.iter_map:
85 if region[0] != 'hooked':
86 continue
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):
91 continue
93 com_committed += region[1]['committed']
94 com_allocs += 1
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':
101 continue
102 else:
103 assert False
104 if (not bucket or
105 (component_name and component_name != component_match)):
106 continue
108 com_committed += committed
109 com_allocs += allocs - frees
111 return com_committed, com_allocs
113 @staticmethod
114 def _output_stacktrace_lines(dump, policy, bucket_set, component_name, out):
115 """Prints information of stacktrace lines for pprof.
117 Args:
118 dump: A Dump object.
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':
126 continue
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):
131 continue
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)
137 out.write('\n')
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':
144 continue
145 else:
146 assert False
147 if (not bucket or
148 (component_name and component_name != component_match)):
149 continue
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)
155 out.write('\n')