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

Unified Diff: tools/win/sizeviewer/sizeviewer.py

Issue 801123002: Improve sizeviewer for Windows (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 6 years 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/win/sizeviewer/main.js ('k') | tools/win/sizeviewer/template.html » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/win/sizeviewer/sizeviewer.py
diff --git a/tools/win/sizeviewer/sizeviewer.py b/tools/win/sizeviewer/sizeviewer.py
index defb00a4b85a5d9cdb60eb2aaf116013eba119b5..3e6d92d03a3956d84e934d382a52bb61f925a396 100644
--- a/tools/win/sizeviewer/sizeviewer.py
+++ b/tools/win/sizeviewer/sizeviewer.py
@@ -2,6 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import base64
+import codecs
import json
import os
import string
@@ -25,12 +27,12 @@ def FindNode(node, component):
def InsertIntoTree(tree, source_name, size):
- components = source_name.replace(':', '').split('\\')
+ components = source_name[3:].split('\\')
node = tree
for index, component in enumerate(components):
data = FindNode(node, component)
if not data:
- data = { 'name': component }
+ data = { 'name': source_name, 'name': component }
if index == len(components) - 1:
data['size'] = size
else:
@@ -39,6 +41,37 @@ def InsertIntoTree(tree, source_name, size):
node = data
+def FlattenTree(tree):
+ result = [['Path', 'Parent', 'Size', 'Value']]
+ def Flatten(node, parent):
+ name = node['name']
+ if parent and parent != '/':
+ name = parent + '/' + name
+ if 'children' in node:
+ result.append([name, parent, -1, -1])
+ for c in node['children']:
+ Flatten(c, name)
+ else:
+ result.append([name, parent, node['size'], node['size']])
+ Flatten(tree, '')
+ return result
+
+
+def GetAsset(filename):
+ with open(os.path.join(BASE_DIR, filename), 'rb') as f:
+ return f.read()
+
+
+def AppendAsScriptBlock(f, value, var=None):
+ f.write('<script type="text/javascript">\n')
+ if var:
+ f.write('var ' + var + ' = ')
+ f.write(value)
+ if var:
+ f.write(';\n')
+ f.write('</script>\n')
+
+
def main():
out_dir = os.path.join(BASE_DIR, '..', '..', '..', 'out', 'Release')
jsons = []
@@ -56,37 +89,99 @@ def main():
print 'Couldn\'t find binaries, looking in', out_dir
return 1
+ # Munge the code_tally json format into an easier-to-view format.
for json_name in jsons:
with open(json_name, 'r') as jsonf:
all_data = json.load(jsonf)
html_path = os.path.splitext(json_name)[0] + '.html'
- print 'Generating %s...' % html_path
+ print 'Generating %s... (standlone)' % html_path
by_source = {}
+ symbols_index = {}
+ symbols = []
for obj_name, obj_data in all_data['objects'].iteritems():
for symbol, symbol_data in obj_data.iteritems():
size = int(symbol_data['size'])
# Sometimes there's symbols with no source file, we just ignore those.
if 'contribs' in symbol_data:
- # There may be more than one file in the list, we just assign to the
- # first source file that contains the symbol, rather than try to
- # split or duplicate info.
- src_index = symbol_data['contribs'][0]
- source = all_data['sources'][int(src_index)]
- if source not in by_source:
- by_source[source] = []
- by_source[source].append(size)
+ i = 0
+ while i < len(symbol_data['contribs']):
+ src_index = symbol_data['contribs'][i]
+ i += 1
+ per_line = symbol_data['contribs'][i]
+ i += 1
+ source = all_data['sources'][int(src_index)]
+ if source not in by_source:
+ by_source[source] = {'lines': {}, 'total_size': 0}
+ size = 0
+ # per_line is [line, size, line, size, line, size, ...]
+ for j in range(0, len(per_line), 2):
+ line_number = per_line[j]
+ size += per_line[j + 1]
+ # Save some time/space in JS by using an array here. 0 == size,
+ # 1 == symbol list.
+ by_source[source]['lines'].setdefault(line_number, [0, []])
+ by_source[source]['lines'][line_number][0] += per_line[j + 1]
+ if symbol in symbols_index:
+ symindex = symbols_index[symbol]
+ else:
+ symbols.append(symbol)
+ symbols_index[symbol] = symindex = len(symbols) - 1
+ by_source[source]['lines'][line_number][1].append(
+ symindex)
+ by_source[source]['total_size'] += size
binary_name = all_data['executable']['name']
data = {}
- data['name'] = binary_name
+ data['name'] = '/'
data['children'] = []
- for source, sizes in by_source.iteritems():
- InsertIntoTree(data, source, sum(sizes))
+ file_contents = {}
+ line_data = {}
+ for source, file_data in by_source.iteritems():
+ InsertIntoTree(data, source, file_data['total_size'])
+
+ store_as = source[3:].replace('\\', '/')
+ try:
+ with codecs.open(source, 'rb', encoding='latin1') as f:
+ file_contents[store_as] = f.read()
+ except IOError:
+ file_contents[store_as] = '// Unable to load source.'
+
+ line_data[store_as] = file_data['lines']
+ # code_tally attempts to assign fractional bytes when code is shared
+ # across multiple symbols. Round off here for display after summing above.
+ for per_line in line_data[store_as].values():
+ per_line[0] = round(per_line[0])
+
+ flattened = FlattenTree(data)
+ maxval = 0
+ for i in flattened[1:]:
+ maxval = max(i[2], maxval)
+ flattened_str = json.dumps(flattened)
+
+ to_write = GetAsset('template.html')
+ # Save all data and what would normally be external resources into the
+ # one html so that it's a standalone report.
with open(html_path, 'w') as f:
- with open(os.path.join(BASE_DIR, 'template.html'), 'r') as templatef:
- template = templatef.read()
- f.write(string.Template(template).substitute(
- {'data': json.dumps(data, indent=2),
- 'dllname': binary_name + ' ' + all_data['executable']['version']}))
+ f.write(to_write)
+ # These aren't subbed in as a silly workaround for 32-bit python.
+ # The end result is only ~100M, but while substituting these into a
+ # template, it otherwise raises a MemoryError, I guess due to
+ # fragmentation. So instead, we just append them as variables to the file
+ # and then refer to the variables in the main script.
+ filedata_str = json.dumps(file_contents).replace(
+ '</script>', '</scr"+"ipt>')
+ AppendAsScriptBlock(f, filedata_str, var='g_file_contents')
+ AppendAsScriptBlock(f, json.dumps(line_data), var='g_line_data')
+ AppendAsScriptBlock(f, json.dumps(symbols), var='g_symbol_list')
+ favicon_str = json.dumps(base64.b64encode(GetAsset('favicon.png')))
+ AppendAsScriptBlock(f, favicon_str, var='g_favicon')
+ AppendAsScriptBlock(f, flattened_str, var='g_raw_data')
+ AppendAsScriptBlock(f, str(maxval), var='g_maxval')
+ dllname_str = binary_name + ' ' + all_data['executable']['version']
+ AppendAsScriptBlock(f, json.dumps(dllname_str), var='g_dllname')
+ AppendAsScriptBlock(f, GetAsset('codemirror.js'))
+ AppendAsScriptBlock(f, GetAsset('clike.js'))
+ AppendAsScriptBlock(f, GetAsset('main.js'))
+ f.write('</html>')
return 0
« no previous file with comments | « tools/win/sizeviewer/main.js ('k') | tools/win/sizeviewer/template.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698