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

Unified Diff: tools/binary_size/file_format.py

Issue 2775173005: FREEZE.unindexed (Closed)
Patch Set: ps2 Created 3 years, 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/binary_size/describe.py ('k') | tools/binary_size/integration_test.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/binary_size/file_format.py
diff --git a/tools/binary_size/file_format.py b/tools/binary_size/file_format.py
index 4f1bbb9180bb67ed2dbd89b9f26a52fad747a748..2e916778518b6b86eec36f1e80e25e200038cf61 100644
--- a/tools/binary_size/file_format.py
+++ b/tools/binary_size/file_format.py
@@ -4,82 +4,148 @@
"""Deals with loading & saving .size files."""
-import ast
+import collections
import gzip
import models
+import logging
+import os
# File format version for .size files.
-_SERIALIZATION_VERSION = 1
-
-
-def EndsWithMaybeGz(path, suffix):
- return path.endswith(suffix) or path.endswith(suffix + '.gz')
-
-
-def OpenMaybeGz(path, mode=None):
- """Calls `gzip.open()` if |path| ends in ".gz", otherwise calls `open()`."""
- if path.endswith('.gz'):
- if mode and 'w' in mode:
- return gzip.GzipFile(path, mode, 1)
- return gzip.open(path, mode)
- return open(path, mode or 'r')
-
-
-def _SaveSizeInfoToFile(result, file_obj):
- """Saves the result to the given file object."""
- # Store one bucket per line.
- file_obj.write('%d\n' % _SERIALIZATION_VERSION)
- file_obj.write('%r\n' % result.section_sizes)
- file_obj.write('%d\n' % len(result.symbols))
- prev_section_name = None
- # Store symbol fields as tab-separated.
- # Store only non-derived fields.
- for symbol in result.symbols:
- if symbol.section_name != prev_section_name:
- file_obj.write('%s\n' % symbol.section_name)
- prev_section_name = symbol.section_name
- # Don't write padding nor name since these are derived values.
- file_obj.write('%x\t%x\t%s\t%s\n' % (
- symbol.address, symbol.size_without_padding,
- symbol.function_signature or symbol.name, symbol.path))
-
-
-def _LoadSizeInfoFromFile(file_obj):
- """Loads a result from the given file."""
- lines = iter(file_obj)
- actual_version = int(next(lines))
+_SERIALIZATION_VERSION = 'Size File Format v1'
+
+
+def _LogSize(file_obj, desc):
+ if not logging.getLogger().isEnabledFor(logging.DEBUG):
+ return
+ file_obj.flush()
+ size = os.fstat(file_obj.fileno()).st_size
+ logging.debug('File size with %s: %d' % (desc, size))
+
+
+def _SaveSizeInfoToFile(size_info, file_obj):
+ file_obj.write('%s\n' % _SERIALIZATION_VERSION)
+ file_obj.write('# Created by //tools/binary_size\n')
+ file_obj.write('%s\n' % '\t'.join(size_info.section_sizes))
+ file_obj.write('%s\n' % '\t'.join(
+ str(v) for v in size_info.section_sizes.itervalues()))
+ _LogSize(file_obj, 'header') # For libchrome: 450 bytes.
+
+ # Store a single copy of all paths and have them referenced by index.
+ # Using an OrderedDict makes the indices more repetitive (better compression).
+ path_tuples = collections.OrderedDict.fromkeys(
+ (s.object_path, s.source_path) for s in size_info.symbols)
+ for i, key in enumerate(path_tuples):
+ path_tuples[key] = i
+ file_obj.write('%d\n' % len(path_tuples))
+ file_obj.writelines('%s\t%s\n' % pair for pair in path_tuples)
+ _LogSize(file_obj, 'paths') # For libchrome, adds 200kb.
+
+ # Symbol counts by section.
+ by_section = size_info.symbols.GroupBySectionName().SortedByName()
+ file_obj.write('%s\n' % '\t'.join(g.name for g in by_section))
+ file_obj.write('%s\n' % '\t'.join(str(len(g)) for g in by_section))
+
+ def write_numeric(func, delta=False):
+ for group in by_section:
+ prev_value = 0
+ last_sym = group[-1]
+ for symbol in group:
+ value = func(symbol)
+ if delta:
+ value, prev_value = value - prev_value, value
+ file_obj.write(str(value))
+ if symbol is not last_sym:
+ file_obj.write(' ')
+ file_obj.write('\n')
+
+ write_numeric(lambda s: s.address, delta=True)
+ _LogSize(file_obj, 'addresses') # For libchrome, adds 300kb.
+ # Do not write padding, it will be recalcualted from addresses on load.
+ write_numeric(lambda s: s.size_without_padding)
+ _LogSize(file_obj, 'sizes') # For libchrome, adds 300kb
+ write_numeric(lambda s: path_tuples[(s.object_path, s.source_path)],
+ delta=True)
+ _LogSize(file_obj, 'path indices') # For libchrome: adds 125kb.
+
+ for group in by_section:
+ for symbol in group:
+ # Do not write name when full_name exists. It will be derived on load.
+ file_obj.write(symbol.full_name or symbol.name)
+ if symbol.is_anonymous:
+ file_obj.write('\t1')
+ file_obj.write('\n')
+ _LogSize(file_obj, 'names (final)') # For libchrome: adds 3.5mb.
+
+
+def _LoadSizeInfoFromFile(lines):
+ """Loads a size_info from the given file."""
+ actual_version = next(lines)[:-1]
assert actual_version == _SERIALIZATION_VERSION, (
'Version mismatch. Need to write some upgrade code.')
-
- section_sizes = ast.literal_eval(next(lines))
- num_syms = int(next(lines))
- symbol_list = [None] * num_syms
- section_name = None
- for i in xrange(num_syms):
- line = next(lines)[:-1]
- if '\t' not in line:
- section_name = line
+ # Comment line.
+ next(lines)
+ section_names = next(lines)[:-1].split('\t')
+ section_values = next(lines)[:-1].split('\t')
+ section_sizes = {k: int(v) for k, v in zip(section_names, section_values)}
+
+ num_path_tuples = int(next(lines))
+ path_tuples = [None] * num_path_tuples
+ for i in xrange(num_path_tuples):
+ path_tuples[i] = next(lines)[:-1].split('\t')
+
+ section_names = next(lines)[:-1].split('\t')
+ section_counts = [int(c) for c in next(lines)[:-1].split('\t')]
+
+ def read_numeric(delta=False):
+ ret = []
+ delta_multiplier = int(delta)
+ for _ in section_counts:
+ value = 0
+ fields = next(lines).split(' ')
+ for i, f in enumerate(fields):
+ value = value * delta_multiplier + int(f)
+ fields[i] = value
+ ret.append(fields)
+ return ret
+
+ addresses = read_numeric(delta=True)
+ sizes = read_numeric(delta=False)
+ path_indices = read_numeric(delta=True)
+
+ symbol_list = [None] * sum(section_counts)
+ symbol_idx = 0
+ for section_index, cur_section_name in enumerate(section_names):
+ for i in xrange(section_counts[section_index]):
line = next(lines)[:-1]
- new_sym = models.Symbol.__new__(models.Symbol)
- parts = line.split('\t')
- new_sym.section_name = section_name
- new_sym.address = int(parts[0], 16)
- new_sym.size = int(parts[1], 16)
- new_sym.name = parts[2]
- new_sym.path = parts[3]
- new_sym.padding = 0 # Derived
- new_sym.function_signature = None # Derived
- symbol_list[i] = new_sym
+ is_anonymous = line.endswith('\t1')
+ name = line[:-2] if is_anonymous else line
+
+ new_sym = models.Symbol.__new__(models.Symbol)
+ new_sym.section_name = cur_section_name
+ new_sym.address = addresses[section_index][i]
+ new_sym.size = sizes[section_index][i]
+ new_sym.name = name
+ paths = path_tuples[path_indices[section_index][i]]
+ new_sym.object_path = paths[0]
+ new_sym.source_path = paths[1]
+ new_sym.is_anonymous = is_anonymous
+ new_sym.padding = 0 # Derived
+ new_sym.full_name = None # Derived
+ symbol_list[symbol_idx] = new_sym
+ symbol_idx += 1
- return models.SizeInfo(models.SymbolGroup(symbol_list), section_sizes)
+ symbols = models.SymbolGroup(symbol_list)
+ return models.SizeInfo(symbols, section_sizes)
-def SaveSizeInfo(result, path):
- with OpenMaybeGz(path, 'wb') as f:
- _SaveSizeInfoToFile(result, f)
+def SaveSizeInfo(size_info, path):
+ """Saves |size_info| to |path}."""
+ with gzip.open(path, 'wb') as f:
+ _SaveSizeInfoToFile(size_info, f)
def LoadSizeInfo(path):
- with OpenMaybeGz(path) as f:
- return _LoadSizeInfoFromFile(f)
+ """Returns a SizeInfo loaded from |path|."""
+ with gzip.open(path) as f:
+ return _LoadSizeInfoFromFile(iter(f))
« no previous file with comments | « tools/binary_size/describe.py ('k') | tools/binary_size/integration_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698