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

Side by Side Diff: tools/binary_size/create_html_breakdown.py

Issue 2778963003: Revert of V2 of //tools/binary_size rewrite (diffs). (Closed)
Patch Set: Created 3 years, 8 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
« no previous file with comments | « tools/binary_size/console.py ('k') | tools/binary_size/describe.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 2014 The Chromium Authors. All rights reserved. 2 # Copyright 2014 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 """Creates an html report that allows you to view binary size by component.""" 6 """Creates an html report that allows you to view binary size by component."""
7 7
8 import argparse 8 import argparse
9 import json 9 import json
10 import logging 10 import logging
11 import os 11 import os
12 import shutil 12 import shutil
13 import sys 13 import sys
14 14
15 import analyze
15 import helpers 16 import helpers
16 import map2size
17 17
18 18
19 # Node dictionary keys. These are output in json read by the webapp so 19 # Node dictionary keys. These are output in json read by the webapp so
20 # keep them short to save file size. 20 # keep them short to save file size.
21 # Note: If these change, the webapp must also change. 21 # Note: If these change, the webapp must also change.
22 _NODE_TYPE_KEY = 'k' 22 _NODE_TYPE_KEY = 'k'
23 _NODE_TYPE_BUCKET = 'b' 23 _NODE_TYPE_BUCKET = 'b'
24 _NODE_TYPE_PATH = 'p' 24 _NODE_TYPE_PATH = 'p'
25 _NODE_TYPE_SYMBOL = 's' 25 _NODE_TYPE_SYMBOL = 's'
26 _NODE_NAME_KEY = 'n' 26 _NODE_NAME_KEY = 'n'
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 node_name = symbol_name or '[Anonymous]' 106 node_name = symbol_name or '[Anonymous]'
107 elif symbol_name.startswith('*'): 107 elif symbol_name.startswith('*'):
108 node_name = symbol_name 108 node_name = symbol_name
109 else: 109 else:
110 node_name = symbol_type 110 node_name = symbol_type
111 node = _GetOrMakeChildNode(node, _NODE_TYPE_SYMBOL, node_name) 111 node = _GetOrMakeChildNode(node, _NODE_TYPE_SYMBOL, node_name)
112 node[_NODE_SYMBOL_SIZE_KEY] = node.get(_NODE_SYMBOL_SIZE_KEY, 0) + symbol_size 112 node[_NODE_SYMBOL_SIZE_KEY] = node.get(_NODE_SYMBOL_SIZE_KEY, 0) + symbol_size
113 node[_NODE_SYMBOL_TYPE_KEY] = symbol_type 113 node[_NODE_SYMBOL_TYPE_KEY] = symbol_type
114 114
115 115
116 def _MakeCompactTree(symbols, include_symbols): 116 def _MakeCompactTree(root_group, include_symbols):
117 result = { 117 result = {
118 _NODE_NAME_KEY: '/', 118 _NODE_NAME_KEY: '/',
119 _NODE_CHILDREN_KEY: {}, 119 _NODE_CHILDREN_KEY: {},
120 _NODE_TYPE_KEY: 'p', 120 _NODE_TYPE_KEY: 'p',
121 _NODE_MAX_DEPTH_KEY: 0, 121 _NODE_MAX_DEPTH_KEY: 0,
122 } 122 }
123 for symbol in symbols: 123 for symbol in root_group:
124 file_path = symbol.path or _NAME_NO_PATH_BUCKET 124 file_path = symbol.path or _NAME_NO_PATH_BUCKET
125 node = result 125 node = result
126 depth = 0 126 depth = 0
127 for path_part in file_path.split(os.path.sep): 127 for path_part in file_path.split(os.path.sep):
128 if not path_part: 128 if not path_part:
129 continue 129 continue
130 depth += 1 130 depth += 1
131 node = _GetOrMakeChildNode(node, _NODE_TYPE_PATH, path_part) 131 node = _GetOrMakeChildNode(node, _NODE_TYPE_PATH, path_part)
132 132
133 symbol_type = symbol.section 133 symbol_type = symbol.section
134 if symbol.name.endswith('[vtable]'): 134 if symbol.name:
135 symbol_type = _NODE_SYMBOL_TYPE_VTABLE 135 if symbol.name.endswith('[vtable]'):
136 elif symbol.name.endswith(']'): 136 symbol_type = _NODE_SYMBOL_TYPE_VTABLE
137 symbol_type = _NODE_SYMBOL_TYPE_GENERATED 137 elif symbol.name.endswith(']'):
138 symbol_type = _NODE_SYMBOL_TYPE_GENERATED
138 _AddSymbolIntoFileNode(node, symbol_type, symbol.name, symbol.size, 139 _AddSymbolIntoFileNode(node, symbol_type, symbol.name, symbol.size,
139 include_symbols) 140 include_symbols)
140 depth += 2 141 depth += 2
141 result[_NODE_MAX_DEPTH_KEY] = max(result[_NODE_MAX_DEPTH_KEY], depth) 142 result[_NODE_MAX_DEPTH_KEY] = max(result[_NODE_MAX_DEPTH_KEY], depth)
142 143
143 # The (no path) bucket can be extremely large if we failed to get 144 # The (no path) bucket can be extremely large if we failed to get
144 # path information. Split it into subgroups if needed. 145 # path information. Split it into subgroups if needed.
145 no_path_bucket = result[_NODE_CHILDREN_KEY].get(_NAME_NO_PATH_BUCKET) 146 no_path_bucket = result[_NODE_CHILDREN_KEY].get(_NAME_NO_PATH_BUCKET)
146 if no_path_bucket and include_symbols: 147 if no_path_bucket and include_symbols:
147 _SplitLargeBucket(no_path_bucket) 148 _SplitLargeBucket(no_path_bucket)
148 149
149 _MakeChildrenDictsIntoLists(result) 150 _MakeChildrenDictsIntoLists(result)
150 151
151 return result 152 return result
152 153
153 154
154 def _CopyTemplateFiles(dest_dir): 155 def _CopyTemplateFiles(dest_dir):
155 d3_out = os.path.join(dest_dir, 'd3') 156 d3_out = os.path.join(dest_dir, 'd3')
156 if not os.path.exists(d3_out): 157 if not os.path.exists(d3_out):
157 os.makedirs(d3_out, 0755) 158 os.makedirs(d3_out, 0755)
158 d3_src = os.path.join(helpers.SRC_ROOT, 'third_party', 'd3', 'src') 159 d3_src = os.path.join(helpers.SRC_ROOT, 'third_party', 'd3', 'src')
159 template_src = os.path.join(os.path.dirname(__file__), 'template') 160 template_src = os.path.join(os.path.dirname(__file__), 'template')
160 shutil.copy(os.path.join(d3_src, 'LICENSE'), d3_out) 161 shutil.copy(os.path.join(d3_src, 'LICENSE'), d3_out)
161 shutil.copy(os.path.join(d3_src, 'd3.js'), d3_out) 162 shutil.copy(os.path.join(d3_src, 'd3.js'), d3_out)
162 shutil.copy(os.path.join(template_src, 'index.html'), dest_dir) 163 shutil.copy(os.path.join(template_src, 'index.html'), dest_dir)
163 shutil.copy(os.path.join(template_src, 'D3SymbolTreeMap.js'), dest_dir) 164 shutil.copy(os.path.join(template_src, 'D3SymbolTreeMap.js'), dest_dir)
164 165
165 166
166 def main(argv): 167 def main():
167 parser = argparse.ArgumentParser() 168 parser = argparse.ArgumentParser()
168 parser.add_argument('input_file',
169 help='Path to input file. Can be a linker .map file, or '
170 'a .size file.')
171 parser.add_argument('--report-dir', metavar='PATH', required=True, 169 parser.add_argument('--report-dir', metavar='PATH', required=True,
172 help='Write output to the specified directory. An HTML ' 170 help='Write output to the specified directory. An HTML '
173 'report is generated here.') 171 'report is generated here.')
174 parser.add_argument('--include-bss', action='store_true', 172 parser.add_argument('--include-bss', action='store_true',
175 help='Include symbols from .bss (which consume no real ' 173 help='Include symbols from .bss (which consume no real '
176 'space)') 174 'space)')
177 parser.add_argument('--include-symbols', action='store_true', 175 parser.add_argument('--include-symbols', action='store_true',
178 help='Use per-symbol granularity rather than per-file.') 176 help='Use per-symbol granularity rather than per-file.')
179 map2size.AddOptions(parser) 177 analyze.AddOptions(parser)
180 args = helpers.AddCommonOptionsAndParseArgs(parser, argv) 178 args = helpers.AddCommonOptionsAndParseArgs(parser)
181 179
182 size_info = map2size.AnalyzeWithArgs(args, args.input_file) 180 result = analyze.AnalyzeWithArgs(args)
183 symbols = size_info.symbols 181 root_group = result.symbol_group
184 if not args.include_bss: 182 if not args.include_bss:
185 symbols = size_info.WhereInSection('b').Inverted() 183 root_group = root_group.WhereInSection('b').Inverted()
186 symbols = symbols.WhereBiggerThan(0) 184 root_group = root_group.WhereBiggerThan(0)
187 185
188 # Copy report boilerplate into output directory. This also proves that the 186 # Copy report boilerplate into output directory. This also proves that the
189 # output directory is safe for writing, so there should be no problems writing 187 # output directory is safe for writing, so there should be no problems writing
190 # the nm.out file later. 188 # the nm.out file later.
191 _CopyTemplateFiles(args.report_dir) 189 _CopyTemplateFiles(args.report_dir)
192 190
193 logging.info('Creating JSON objects') 191 logging.info('Creating JSON objects')
194 tree_root = _MakeCompactTree(symbols, args.include_symbols) 192 tree_root = _MakeCompactTree(root_group, args.include_symbols)
195 193
196 logging.info('Serializing') 194 logging.info('Serializing')
197 with open(os.path.join(args.report_dir, 'data.js'), 'w') as out_file: 195 with open(os.path.join(args.report_dir, 'data.js'), 'w') as out_file:
198 out_file.write('var tree_data=') 196 out_file.write('var tree_data=')
199 # Use separators without whitespace to get a smaller file. 197 # Use separators without whitespace to get a smaller file.
200 json.dump(tree_root, out_file, ensure_ascii=False, check_circular=False, 198 json.dump(tree_root, out_file, ensure_ascii=False, check_circular=False,
201 separators=(',', ':')) 199 separators=(',', ':'))
202 200
203 print 'Report saved to ' + args.report_dir + '/index.html' 201 print 'Report saved to ' + args.report_dir + '/index.html'
204 202
205
206 if __name__ == '__main__': 203 if __name__ == '__main__':
207 sys.exit(main(sys.argv)) 204 sys.exit(main())
OLDNEW
« no previous file with comments | « tools/binary_size/console.py ('k') | tools/binary_size/describe.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698