Commit 23a89da8 authored by Samuel Huang's avatar Samuel Huang Committed by Commit Bot

[SuperSize] Rework SymbolGroup unique Symbols iteration.

DeltaSymbolGroup.CountUniqueSymbols() sums separate unique leaf symbol
counts in "before" and "after". Previously this was done via temporary
SymbolGroups and using their CountUniqueSymbols().

As a memory optimization, both temporary SymbolGroups were given Symbol
iterators at construction. However, the |_symbols| member become single-
use as a result. This violates the immutability property of the object,
and causes problem as we plan to process |_symbols| in upcoming work to
add multi-container support.

A short fix is to convert input and make |_symbols| as a list, but this
is opaque, and undoes the optimization above. This CL makes the
following changes instead:

* Assert that SymbolGroup() is given list at construction.
* Replace SymbolGroups.IterUniqueSymbols() with a static generator
  SymbolGroups.IterUnique() that takes an input iterator.
  * All callers undergo minor change.
  * Callers of {Delta}SymbolGroups.CountUniqueSymbol() are unchanged.
* Update DeltaSymbolGroup.CountUniqueSymbols() to use the new interface,
  without needing temporary SymbolGroups. Optimization is kept.

Bug: 1040645
Change-Id: I32c3867fe006a078f9a6ddcf764349b360120e9a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2204304
Commit-Queue: Samuel Huang <huangs@chromium.org>
Reviewed-by: default avatarAndrew Grieve <agrieve@chromium.org>
Cr-Commit-Position: refs/heads/master@{#769997}
parent 991b4824
...@@ -626,6 +626,7 @@ class SymbolGroup(BaseSymbol): ...@@ -626,6 +626,7 @@ class SymbolGroup(BaseSymbol):
name='', name='',
section_name=None, section_name=None,
is_default_sorted=False): is_default_sorted=False):
assert isinstance(symbols, list) # Rejects non-reusable generators.
self._padding = None self._padding = None
self._size = None self._size = None
self._pss = None self._pss = None
...@@ -744,16 +745,20 @@ class SymbolGroup(BaseSymbol): ...@@ -744,16 +745,20 @@ class SymbolGroup(BaseSymbol):
self.template_name = full_name if template_name is None else template_name self.template_name = full_name if template_name is None else template_name
self.name = full_name if name is None else name self.name = full_name if name is None else name
def IterUniqueSymbols(self): @staticmethod
"""Yields all symbols, but only one from each alias group.""" def _IterUnique(symbol_iter):
seen_aliases_lists = set() seen_aliases_lists = set()
for s in self: for s in symbol_iter:
if not s.aliases: if not s.aliases:
yield s yield s
elif id(s.aliases) not in seen_aliases_lists: elif id(s.aliases) not in seen_aliases_lists:
seen_aliases_lists.add(id(s.aliases)) seen_aliases_lists.add(id(s.aliases))
yield s yield s
def IterUniqueSymbols(self):
"""Yields all symbols, but only one from each alias group."""
return SymbolGroup._IterUnique(self)
def IterLeafSymbols(self): def IterLeafSymbols(self):
"""Yields all symbols, recursing into subgroups.""" """Yields all symbols, recursing into subgroups."""
for s in self: for s in self:
...@@ -775,14 +780,13 @@ class SymbolGroup(BaseSymbol): ...@@ -775,14 +780,13 @@ class SymbolGroup(BaseSymbol):
is_default_sorted = self.is_default_sorted is_default_sorted = self.is_default_sorted
if section_name is None: if section_name is None:
section_name = self.section_name section_name = self.section_name
return self.__class__( return self.__class__(symbols,
symbols, filtered_symbols=filtered_symbols,
filtered_symbols=filtered_symbols, full_name=full_name,
full_name=full_name, template_name=template_name,
template_name=template_name, name=name,
name=name, section_name=section_name,
section_name=section_name, is_default_sorted=is_default_sorted)
is_default_sorted=is_default_sorted)
def Sorted(self, cmp_func=None, key=None, reverse=False): def Sorted(self, cmp_func=None, key=None, reverse=False):
"""Sorts by abs(PSS).""" """Sorts by abs(PSS)."""
...@@ -937,10 +941,9 @@ class SymbolGroup(BaseSymbol): ...@@ -937,10 +941,9 @@ class SymbolGroup(BaseSymbol):
# Symbols within third_party that do not contain the string "foo". # Symbols within third_party that do not contain the string "foo".
symbols.WherePathMatches(r'third_party').WhereMatches('foo').Inverted() symbols.WherePathMatches(r'third_party').WhereMatches('foo').Inverted()
""" """
return self._CreateTransformed( return self._CreateTransformed(self._filtered_symbols,
self._filtered_symbols, filtered_symbols=self._symbols,
filtered_symbols=self._symbols, section_name=SECTION_MULTIPLE)
section_name=SECTION_MULTIPLE)
def GroupedBy(self, func, min_count=0, group_factory=None): def GroupedBy(self, func, min_count=0, group_factory=None):
"""Returns a SymbolGroup of SymbolGroups, indexed by |func|. """Returns a SymbolGroup of SymbolGroups, indexed by |func|.
...@@ -1042,18 +1045,16 @@ class SymbolGroup(BaseSymbol): ...@@ -1042,18 +1045,16 @@ class SymbolGroup(BaseSymbol):
full_name = token[1] full_name = token[1]
sym = symbols[0] sym = symbols[0]
if token[1].startswith('*'): if token[1].startswith('*'):
return self._CreateTransformed( return self._CreateTransformed(symbols,
symbols, full_name=full_name,
full_name=full_name, template_name=full_name,
template_name=full_name, name=full_name,
name=full_name, section_name=sym.section_name)
section_name=sym.section_name) return self._CreateTransformed(symbols,
return self._CreateTransformed( full_name=full_name,
symbols, template_name=sym.template_name,
full_name=full_name, name=sym.name,
template_name=sym.template_name, section_name=sym.section_name)
name=sym.name,
section_name=sym.section_name)
# A full second faster to cluster per-section. Plus, don't need create # A full second faster to cluster per-section. Plus, don't need create
# (section_name, name) tuples in cluster_func. # (section_name, name) tuples in cluster_func.
...@@ -1080,12 +1081,11 @@ class SymbolGroup(BaseSymbol): ...@@ -1080,12 +1081,11 @@ class SymbolGroup(BaseSymbol):
""" """
def group_factory(_, symbols): def group_factory(_, symbols):
sym = symbols[0] sym = symbols[0]
return self._CreateTransformed( return self._CreateTransformed(symbols,
symbols, full_name=sym.full_name,
full_name=sym.full_name, template_name=sym.template_name,
template_name=sym.template_name, name=sym.name,
name=sym.name, section_name=sym.section_name)
section_name=sym.section_name)
return self.GroupedBy( return self.GroupedBy(
lambda s: (same_name_only and s.full_name, id(s.aliases or s)), lambda s: (same_name_only and s.full_name, id(s.aliases or s)),
...@@ -1195,10 +1195,12 @@ class DeltaSymbolGroup(SymbolGroup): ...@@ -1195,10 +1195,12 @@ class DeltaSymbolGroup(SymbolGroup):
def CountUniqueSymbols(self): def CountUniqueSymbols(self):
"""Returns (num_unique_before_symbols, num_unique_after_symbols).""" """Returns (num_unique_before_symbols, num_unique_after_symbols)."""
syms = (s.before_symbol for s in self.IterLeafSymbols() if s.before_symbol) syms_iter = (s.before_symbol for s in self.IterLeafSymbols()
before_count = SymbolGroup(syms).CountUniqueSymbols() if s.before_symbol)
syms = (s.after_symbol for s in self.IterLeafSymbols() if s.after_symbol) before_count = sum(1 for _ in SymbolGroup._IterUnique(syms_iter))
after_count = SymbolGroup(syms).CountUniqueSymbols() syms_iter = (s.after_symbol for s in self.IterLeafSymbols()
if s.after_symbol)
after_count = sum(1 for _ in SymbolGroup._IterUnique(syms_iter))
return before_count, after_count return before_count, after_count
@property @property
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment