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

Side by Side Diff: tools/binary_size/libsupersize/models.py

Issue 2924343004: supersize: Fix path counts, missing section in clusters (Closed)
Patch Set: add comments Created 3 years, 6 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/libsupersize/diff.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2017 The Chromium Authors. All rights reserved. 1 # Copyright 2017 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 """Classes that comprise the data model for binary size analysis. 4 """Classes that comprise the data model for binary size analysis.
5 5
6 The primary classes are Symbol, and SymbolGroup. 6 The primary classes are Symbol, and SymbolGroup.
7 7
8 Description of common properties: 8 Description of common properties:
9 * address: The start address of the symbol. 9 * address: The start address of the symbol.
10 May be 0 (e.g. for .bss or for SymbolGroups). 10 May be 0 (e.g. for .bss or for SymbolGroups).
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 METADATA_GN_ARGS = 'gn_args' 43 METADATA_GN_ARGS = 'gn_args'
44 METADATA_TOOL_PREFIX = 'tool_prefix' # Path relative to SRC_ROOT. 44 METADATA_TOOL_PREFIX = 'tool_prefix' # Path relative to SRC_ROOT.
45 45
46 46
47 SECTION_TO_SECTION_NAME = { 47 SECTION_TO_SECTION_NAME = {
48 'b': '.bss', 48 'b': '.bss',
49 'd': '.data', 49 'd': '.data',
50 'r': '.rodata', 50 'r': '.rodata',
51 't': '.text', 51 't': '.text',
52 } 52 }
53 # Used by SymbolGroup when they contain a mix of sections.
54 SECTION_NAME_MULTIPLE = '.*'
53 55
54 FLAG_ANONYMOUS = 1 56 FLAG_ANONYMOUS = 1
55 FLAG_STARTUP = 2 57 FLAG_STARTUP = 2
56 FLAG_UNLIKELY = 4 58 FLAG_UNLIKELY = 4
57 FLAG_REL = 8 59 FLAG_REL = 8
58 FLAG_REL_LOCAL = 16 60 FLAG_REL_LOCAL = 16
59 FLAG_GENERATED_SOURCE = 32 61 FLAG_GENERATED_SOURCE = 32
60 FLAG_CLONE = 64 62 FLAG_CLONE = 64
61 63
62 DIFF_STATUS_UNCHANGED = 0 64 DIFF_STATUS_UNCHANGED = 0
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 def __init__(self, symbols, filtered_symbols=None, full_name=None, 306 def __init__(self, symbols, filtered_symbols=None, full_name=None,
305 template_name=None, name='', section_name=None, is_sorted=False): 307 template_name=None, name='', section_name=None, is_sorted=False):
306 self._padding = None 308 self._padding = None
307 self._size = None 309 self._size = None
308 self._pss = None 310 self._pss = None
309 self._symbols = symbols 311 self._symbols = symbols
310 self._filtered_symbols = filtered_symbols or [] 312 self._filtered_symbols = filtered_symbols or []
311 self.full_name = full_name if full_name is not None else name 313 self.full_name = full_name if full_name is not None else name
312 self.template_name = template_name if template_name is not None else name 314 self.template_name = template_name if template_name is not None else name
313 self.name = name or '' 315 self.name = name or ''
314 self.section_name = section_name or '.*' 316 self.section_name = section_name or SECTION_NAME_MULTIPLE
315 self.is_sorted = is_sorted 317 self.is_sorted = is_sorted
316 318
317 def __repr__(self): 319 def __repr__(self):
318 return 'Group(full_name=%s,count=%d,size=%d)' % ( 320 return 'Group(full_name=%s,count=%d,size=%d)' % (
319 self.full_name, len(self), self.size) 321 self.full_name, len(self), self.size)
320 322
321 def __iter__(self): 323 def __iter__(self):
322 return iter(self._symbols) 324 return iter(self._symbols)
323 325
324 def __len__(self): 326 def __len__(self):
325 return len(self._symbols) 327 return len(self._symbols)
326 328
327 def __eq__(self, other): 329 def __eq__(self, other):
328 return isinstance(other, SymbolGroup) and self._symbols == other._symbols 330 return isinstance(other, SymbolGroup) and self._symbols == other._symbols
329 331
330 def __getitem__(self, key): 332 def __getitem__(self, key):
331 """|key| can be an index or an address. 333 """|key| can be an index or an address.
332 334
333 Raises if multiple symbols map to the address. 335 Raises if multiple symbols map to the address.
334 """ 336 """
335 if isinstance(key, slice): 337 if isinstance(key, slice):
336 return self._symbols.__getitem__(key) 338 return self._CreateTransformed(self._symbols.__getitem__(key))
337 if isinstance(key, basestring) or key > len(self._symbols): 339 if isinstance(key, basestring) or key > len(self._symbols):
338 found = self.WhereAddressInRange(key) 340 found = self.WhereAddressInRange(key)
339 if len(found) != 1: 341 if len(found) != 1:
340 raise KeyError('%d symbols found at address %s.' % (len(found), key)) 342 raise KeyError('%d symbols found at address %s.' % (len(found), key))
341 return found[0] 343 return found[0]
342 return self._symbols[key] 344 return self._symbols[key]
343 345
344 def __sub__(self, other): 346 def __sub__(self, other):
345 other_ids = set(id(s) for s in other) 347 other_ids = set(id(s) for s in other)
346 after_symbols = [s for s in self if id(s) not in other_ids] 348 after_symbols = [s for s in self if id(s) not in other_ids]
347 return self._CreateTransformed(after_symbols, 349 return self._CreateTransformed(after_symbols)
348 section_name=self.section_name)
349 350
350 def __add__(self, other): 351 def __add__(self, other):
351 self_ids = set(id(s) for s in self) 352 self_ids = set(id(s) for s in self)
352 after_symbols = self._symbols + [s for s in other if id(s) not in self_ids] 353 after_symbols = self._symbols + [s for s in other if id(s) not in self_ids]
353 return self._CreateTransformed( 354 return self._CreateTransformed(after_symbols, is_sorted=False)
354 after_symbols, section_name=self.section_name, is_sorted=False)
355 355
356 @property 356 @property
357 def address(self): 357 def address(self):
358 first = self._symbols[0].address if self else 0 358 first = self._symbols[0].address if self else 0
359 return first if all(s.address == first for s in self._symbols) else 0 359 return first if all(s.address == first for s in self._symbols) else 0
360 360
361 @property 361 @property
362 def flags(self): 362 def flags(self):
363 first = self._symbols[0].flags if self else 0 363 first = self._symbols[0].flags if self else 0
364 return first if all(s.flags == first for s in self._symbols) else 0 364 return first if all(s.flags == first for s in self._symbols) else 0
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
429 yield s 429 yield s
430 430
431 def CountUniqueSymbols(self): 431 def CountUniqueSymbols(self):
432 return sum(1 for s in self.IterUniqueSymbols()) 432 return sum(1 for s in self.IterUniqueSymbols())
433 433
434 def _CreateTransformed(self, symbols, filtered_symbols=None, full_name=None, 434 def _CreateTransformed(self, symbols, filtered_symbols=None, full_name=None,
435 template_name=None, name=None, section_name=None, 435 template_name=None, name=None, section_name=None,
436 is_sorted=None): 436 is_sorted=None):
437 if is_sorted is None: 437 if is_sorted is None:
438 is_sorted = self.is_sorted 438 is_sorted = self.is_sorted
439 if section_name is None:
440 section_name = self.section_name
439 return SymbolGroup(symbols, filtered_symbols=filtered_symbols, 441 return SymbolGroup(symbols, filtered_symbols=filtered_symbols,
440 full_name=full_name, template_name=template_name, 442 full_name=full_name, template_name=template_name,
441 name=name, section_name=section_name, 443 name=name, section_name=section_name,
442 is_sorted=is_sorted) 444 is_sorted=is_sorted)
443 445
444 def Sorted(self, cmp_func=None, key=None, reverse=False): 446 def Sorted(self, cmp_func=None, key=None, reverse=False):
445 if cmp_func is None and key is None: 447 if cmp_func is None and key is None:
446 cmp_func = lambda a, b: cmp((a.IsBss(), abs(b.pss), a.name), 448 cmp_func = lambda a, b: cmp((a.IsBss(), abs(b.pss), a.name),
447 (b.IsBss(), abs(a.pss), b.name)) 449 (b.IsBss(), abs(a.pss), b.name))
448 450
449 after_symbols = sorted(self._symbols, cmp_func, key, reverse) 451 after_symbols = sorted(self._symbols, cmp_func, key, reverse)
450 return self._CreateTransformed( 452 return self._CreateTransformed(
451 after_symbols, filtered_symbols=self._filtered_symbols, 453 after_symbols, filtered_symbols=self._filtered_symbols,
452 section_name=self.section_name, is_sorted=True) 454 is_sorted=True)
453 455
454 def SortedByName(self, reverse=False): 456 def SortedByName(self, reverse=False):
455 return self.Sorted(key=(lambda s:s.name), reverse=reverse) 457 return self.Sorted(key=(lambda s:s.name), reverse=reverse)
456 458
457 def SortedByAddress(self, reverse=False): 459 def SortedByAddress(self, reverse=False):
458 return self.Sorted(key=(lambda s:(s.address, s.object_path, s.name)), 460 return self.Sorted(key=(lambda s:(s.address, s.object_path, s.name)),
459 reverse=reverse) 461 reverse=reverse)
460 462
461 def SortedByCount(self, reverse=False): 463 def SortedByCount(self, reverse=False):
462 return self.Sorted(key=(lambda s:len(s) if s.IsGroup() else 1), 464 return self.Sorted(key=(lambda s:len(s) if s.IsGroup() else 1),
463 reverse=not reverse) 465 reverse=not reverse)
464 466
465 def Filter(self, func): 467 def Filter(self, func):
466 filtered_and_kept = ([], []) 468 filtered_and_kept = ([], [])
467 symbol = None 469 symbol = None
468 try: 470 try:
469 for symbol in self: 471 for symbol in self:
470 filtered_and_kept[int(bool(func(symbol)))].append(symbol) 472 filtered_and_kept[int(bool(func(symbol)))].append(symbol)
471 except: 473 except:
472 logging.warning('Filter failed on symbol %r', symbol) 474 logging.warning('Filter failed on symbol %r', symbol)
473 raise 475 raise
474 476
475 return self._CreateTransformed(filtered_and_kept[1], 477 return self._CreateTransformed(filtered_and_kept[1],
476 filtered_symbols=filtered_and_kept[0], 478 filtered_symbols=filtered_and_kept[0])
477 section_name=self.section_name)
478 479
479 def WhereIsGroup(self): 480 def WhereIsGroup(self):
480 return self.Filter(lambda s: s.IsGroup()) 481 return self.Filter(lambda s: s.IsGroup())
481 482
482 def WhereSizeBiggerThan(self, min_size): 483 def WhereSizeBiggerThan(self, min_size):
483 return self.Filter(lambda s: s.size >= min_size) 484 return self.Filter(lambda s: s.size >= min_size)
484 485
485 def WherePssBiggerThan(self, min_pss): 486 def WherePssBiggerThan(self, min_pss):
486 return self.Filter(lambda s: s.pss >= min_pss) 487 return self.Filter(lambda s: s.pss >= min_pss)
487 488
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
560 561
561 Applies only when the previous call was a filter. 562 Applies only when the previous call was a filter.
562 563
563 Example: 564 Example:
564 # Symbols that do not have "third_party" in their path. 565 # Symbols that do not have "third_party" in their path.
565 symbols.WherePathMatches(r'third_party').Inverted() 566 symbols.WherePathMatches(r'third_party').Inverted()
566 # Symbols within third_party that do not contain the string "foo". 567 # Symbols within third_party that do not contain the string "foo".
567 symbols.WherePathMatches(r'third_party').WhereMatches('foo').Inverted() 568 symbols.WherePathMatches(r'third_party').WhereMatches('foo').Inverted()
568 """ 569 """
569 return self._CreateTransformed( 570 return self._CreateTransformed(
570 self._filtered_symbols, filtered_symbols=self._symbols, is_sorted=False) 571 self._filtered_symbols, filtered_symbols=self._symbols,
572 section_name=SECTION_NAME_MULTIPLE, is_sorted=False)
571 573
572 def GroupedBy(self, func, min_count=0, group_factory=None): 574 def GroupedBy(self, func, min_count=0, group_factory=None):
573 """Returns a SymbolGroup of SymbolGroups, indexed by |func|. 575 """Returns a SymbolGroup of SymbolGroups, indexed by |func|.
574 576
575 Symbols within each subgroup maintain their relative ordering. 577 Symbols within each subgroup maintain their relative ordering.
576 578
577 Args: 579 Args:
578 func: Grouping function. Passed a symbol and returns a string for the 580 func: Grouping function. Passed a symbol and returns a string for the
579 name of the subgroup to put the symbol in. If None is returned, the 581 name of the subgroup to put the symbol in. If None is returned, the
580 symbol is omitted. 582 symbol is omitted.
581 min_count: Miniumum number of symbols for a group. If fewer than this many 583 min_count: Miniumum number of symbols for a group. If fewer than this many
582 symbols end up in a group, they will not be put within a group. 584 symbols end up in a group, they will not be put within a group.
583 Use a negative value to omit symbols entirely rather than 585 Use a negative value to omit symbols entirely rather than
584 include them outside of a group. 586 include them outside of a group.
585 group_factory: Function to create SymbolGroup from a list of Symbols. 587 group_factory: Function to create SymbolGroup from a list of Symbols.
586 """ 588 """
587 if group_factory is None: 589 if group_factory is None:
588 group_factory = lambda token, symbols: self._CreateTransformed( 590 group_factory = lambda token, symbols: self._CreateTransformed(
589 symbols, full_name=token, template_name=token, name=token, 591 symbols, full_name=token, template_name=token, name=token)
590 section_name=self.section_name)
591 592
592 after_syms = [] 593 after_syms = []
593 filtered_symbols = [] 594 filtered_symbols = []
594 symbols_by_token = collections.OrderedDict() 595 symbols_by_token = collections.OrderedDict()
595 # Index symbols by |func|. 596 # Index symbols by |func|.
596 for symbol in self: 597 for symbol in self:
597 token = func(symbol) 598 token = func(symbol)
598 if token is None: 599 if token is None:
599 filtered_symbols.append(symbol) 600 filtered_symbols.append(symbol)
600 else: 601 else:
(...skipping 18 matching lines...) Expand all
619 symbol_or_list = [symbol_or_list] 620 symbol_or_list = [symbol_or_list]
620 after_syms.append(group_factory(token, symbol_or_list)) 621 after_syms.append(group_factory(token, symbol_or_list))
621 else: 622 else:
622 target_list = after_syms if include_singles else filtered_symbols 623 target_list = after_syms if include_singles else filtered_symbols
623 if count == 1: 624 if count == 1:
624 target_list.append(symbol_or_list) 625 target_list.append(symbol_or_list)
625 else: 626 else:
626 target_list.extend(symbol_or_list) 627 target_list.extend(symbol_or_list)
627 628
628 return self._CreateTransformed( 629 return self._CreateTransformed(
629 after_syms, filtered_symbols=filtered_symbols, 630 after_syms, filtered_symbols=filtered_symbols)
630 section_name=self.section_name)
631 631
632 def _Clustered(self): 632 def _Clustered(self):
633 """Returns a new SymbolGroup with some symbols moved into subgroups. 633 """Returns a new SymbolGroup with some symbols moved into subgroups.
634 634
635 Method is private since it only ever makes sense to call it from 635 Method is private since it only ever makes sense to call it from
636 SizeInfo.symbols. 636 SizeInfo.symbols.
637 637
638 The main function of clustering is to put symbols that were broken into 638 The main function of clustering is to put symbols that were broken into
639 multiple parts under a group so that they once again look like a single 639 multiple parts under a group so that they once again look like a single
640 symbol. It also groups together symbols like "** merge strings". 640 symbol. It also groups together symbols like "** merge strings".
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
862 862
863 863
864 def _ExtractSuffixAfterSeparator(string, separator, count): 864 def _ExtractSuffixAfterSeparator(string, separator, count):
865 prev_idx = len(string) + 1 865 prev_idx = len(string) + 1
866 for _ in xrange(count): 866 for _ in xrange(count):
867 idx = string.rfind(separator, 0, prev_idx - 1) 867 idx = string.rfind(separator, 0, prev_idx - 1)
868 if idx < 0: 868 if idx < 0:
869 break 869 break
870 prev_idx = idx 870 prev_idx = idx
871 return string[:prev_idx] 871 return string[:prev_idx]
OLDNEW
« no previous file with comments | « tools/binary_size/libsupersize/diff.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698