| # Copyright 2017 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Contains a set of Chrome-specific size queries.""" |
| |
| import logging |
| import re |
| |
| import models |
| |
| |
| class _Grouper: |
| def __init__(self): |
| self.groups = [] |
| |
| def Add(self, name, group): |
| logging.debug('Computed %s (%d syms)', name, len(group)) |
| if group: |
| sorted_group = group.Sorted() |
| sorted_group.SetName(name) |
| self.groups.append(sorted_group) |
| return group.Inverted() |
| |
| def Finalize(self, remaining): |
| self.groups.sort(key=lambda s:(s.name.startswith('Other'), -abs(s.pss))) |
| if remaining: |
| stars = remaining.Filter(lambda s: s.name.startswith('*')) |
| if stars: |
| remaining = stars.Inverted() |
| stars = stars.Sorted() |
| stars.SetName('** Merged Symbols') |
| self.groups.append(stars) |
| |
| others_by_path = remaining.GroupedByPath(depth=1).Sorted() |
| for subgroup in others_by_path: |
| subgroup.SetName('Other //' + subgroup.name) |
| self.groups.extend(others_by_path) |
| |
| logging.debug('Finalized') |
| return models.SymbolGroup(self.groups) |
| |
| |
| def _CategorizeByChromeComponent(symbols): |
| g = _Grouper() |
| |
| # Put things that filter out a lot of symbols at the beginning where possible |
| # to optimize speed. |
| symbols = g.Add('WebRTC', symbols.WhereMatches(r'(?i)webrtc')) |
| symbols = g.Add('v8', symbols.Filter( |
| lambda s: s.source_path.startswith('v8/'))) |
| symbols = g.Add('Skia', symbols.Filter(lambda s: 'skia/' in s.source_path)) |
| symbols = g.Add('net', symbols.Filter( |
| lambda s: s.source_path.startswith('net/'))) |
| symbols = g.Add('media', symbols.Filter( |
| lambda s: s.source_path.startswith('media/'))) |
| symbols = g.Add('gpu', symbols.Filter( |
| lambda s: s.source_path.startswith('gpu/'))) |
| symbols = g.Add('cc', symbols.Filter( |
| lambda s: s.source_path.startswith('cc/'))) |
| symbols = g.Add('base', symbols.Filter( |
| lambda s: s.source_path.startswith('base/'))) |
| symbols = g.Add('viz', symbols.Filter( |
| lambda s: s.source_path.startswith('components/viz'))) |
| symbols = g.Add('ui/gfx', symbols.Filter( |
| lambda s: s.source_path.startswith('ui/gfx/'))) |
| |
| # Next, put non-regex queries, since they're a bit faster. |
| symbols = g.Add('ICU', symbols.Filter(lambda s: '/icu/' in s.source_path)) |
| symbols = g.Add('Prefetch', symbols.Filter( |
| lambda s: 'resource_prefetch' in s.source_path)) |
| symbols = g.Add('Password Manager', symbols.Filter( |
| lambda s: 'password_manager' in s.source_path)) |
| symbols = g.Add('Internals Pages', symbols.Filter( |
| lambda s: '_internals' in s.source_path)) |
| symbols = g.Add('Autofill', symbols.WhereSourcePathMatches(r'(?i)autofill')) |
| symbols = g.Add('WebGL', symbols.WhereMatches(r'(?i)webgl')) |
| symbols = g.Add('WebBluetooth', symbols.WhereMatches(r'(?i)bluetooth')) |
| symbols = g.Add('WebUSB', symbols.WhereMatches(r'(?i)webusb|(\b|_)usb(\b|_)')) |
| symbols = g.Add('WebVR', symbols.WhereMatches( |
| r'{{_gvr_}}|{{_cwebvr_}}|{{_vr_}}')) |
| symbols = g.Add('FileSystem', symbols.WhereSourcePathMatches( |
| r'content/.*/fileapi|WebKit/.*/filesystem')) |
| symbols = g.Add('WebCrypto', symbols.WhereMatches(r'(?i)webcrypto')) |
| symbols = g.Add('Printing', symbols.WhereMatches(r'printing')) |
| symbols = g.Add('Cast', symbols.WhereSourcePathMatches( |
| r'(?i)(\b|_)cast(\b|_)')) |
| symbols = g.Add('Media Source', symbols.WhereMatches( |
| r'(?i)mediasource|blink::.*TrackDefault|blink::.*SourceBuffer')) |
| |
| # XSLT must come before libxml. |
| symbols = g.Add('XSLT', symbols.WhereMatches(r'(?i)xslt')) |
| symbols = g.Add('libxml', symbols.Filter( |
| lambda s: 'libxml' in s.source_path)) |
| |
| # These have some overlap with above, so need to come afterwards. |
| blink_syms = symbols.WhereSourcePathMatches(r'\b(blink|WebKit)\b') |
| symbols = blink_syms.Inverted() |
| blink_generated = blink_syms.WhereSourceIsGenerated() |
| g.Add('Blink (generated)', blink_generated) |
| g.Add('Blink (non-generated)', blink_generated.Inverted()) |
| |
| symbols = g.Add('Codecs', symbols.WhereSourcePathMatches( |
| r'^third_party/(libweb[mp]|libpng|libjpeg_turbo|opus|ffmpeg|libvpx)/')) |
| symbols = g.Add('Other Third-Party', symbols.Filter( |
| lambda s: 'third_party' in s.source_path)) |
| |
| return g.Finalize(symbols) |
| |
| |
| def _CategorizeGenerated(symbols): |
| g = _Grouper() |
| |
| # Don't count other symbols or prebuilts. |
| symbols = symbols.Filter(lambda s: s.section_name != models.SECTION_OTHER and |
| not s.source_path.endswith('.class')) |
| # JNI is generated into .h files then #included, so the symbols don't actaully |
| # appear as "SourceIsGenerated". |
| # Note: String literals within symbols like "kBaseRegisteredMethods" are not |
| # being accounted for here because they end up within "** merge strings". |
| # This could be fixed by assigning them all to proper variables rather |
| # than having them be inline. |
| symbols = g.Add('RegisterJNI', symbols.WhereFullNameMatches( |
| r'Register.*JNIEnv\*\)|RegisteredMethods$')) |
| symbols = g.Add('gl_bindings_autogen', |
| symbols.WherePathMatches('gl_bindings_autogen')) |
| |
| symbols = symbols.WhereSourceIsGenerated() |
| symbols = g.Add( |
| 'Java Protocol Buffers', |
| symbols.Filter(lambda s: '__protoc_java.srcjar' in s.source_path)) |
| symbols = g.Add('C++ Protocol Buffers', symbols.Filter(lambda s: ( |
| '/protobuf/' in s.object_path or |
| s.object_path.endswith('.pbzero.o') or |
| s.object_path.endswith('.pb.o')))) |
| mojo_pattern = re.compile(r'\bmojom?\b') |
| symbols = g.Add( |
| 'Mojo', |
| symbols.Filter(lambda s: (s.full_name.startswith('mojo::') or mojo_pattern |
| .search(s.source_path)))) |
| symbols = g.Add('DevTools', symbols.WhereSourcePathMatches( |
| r'\b(?:protocol|devtools)\b')) |
| symbols = g.Add('Blink (bindings)', symbols.WherePathMatches( |
| r'(?:blink|WebKit)/.*bindings')) |
| symbols = g.Add('Blink (other)', symbols.Filter(lambda s: ( |
| 'WebKit' in s.object_path or 'blink/' in s.object_path))) |
| symbols = g.Add('V8 Builtins', symbols.Filter(lambda s: ( |
| s.source_path.endswith('embedded.S')))) |
| symbols = g.Add('prepopulated_engines.cc', symbols.Filter(lambda s: ( |
| 'prepopulated_engines' in s.object_path))) |
| symbols = g.Add('Metrics-related code', symbols.Filter(lambda s: ( |
| '/metrics/' in s.object_path))) |
| symbols = g.Add('gpu_driver_bug_list_autogen.cc', symbols.Filter(lambda s: ( |
| 'gpu_driver_bug_list' in s.object_path))) |
| symbols = g.Add('components/policy', symbols.Filter(lambda s: ( |
| 'components/policy' in s.object_path))) |
| |
| return g.Finalize(symbols) |
| |
| |
| class CannedQueries: |
| """A set of pre-written queries.""" |
| |
| def __init__(self, size_infos): |
| self._size_infos = size_infos |
| |
| def _SymbolsArg(self, arg, native_only=False, pak_only=False): |
| arg = arg if arg is not None else self._size_infos[-1] |
| if isinstance(arg, models.BaseSizeInfo): |
| if native_only: |
| arg = arg.native_symbols |
| elif pak_only: |
| arg = arg.pak_symbols |
| else: |
| arg = arg.symbols |
| return arg |
| |
| def CategorizeGenerated(self, symbols=None): |
| """Categorizes symbols that come from generated source files.""" |
| return _CategorizeGenerated(self._SymbolsArg(symbols)) |
| |
| def CategorizeByChromeComponent(self, symbols=None): |
| """Groups symbols by component using predefined queries.""" |
| return _CategorizeByChromeComponent(self._SymbolsArg(symbols)) |
| |
| def TemplatesByName(self, symbols=None, depth=0): |
| """Lists C++ templates grouped by name.""" |
| symbols = self._SymbolsArg(symbols, native_only=True) |
| # Call Sorted() twice so that subgroups will be sorted. |
| # TODO(agrieve): Might be nice to recursively GroupedByName() on these. |
| return symbols.WhereIsTemplate().Sorted().GroupedByName(depth).Sorted() |
| |
| def StaticInitializers(self, symbols=None): |
| """Lists Static Initializers.""" |
| symbols = self._SymbolsArg(symbols, native_only=True) |
| # GCC generates "_GLOBAL__" symbols. Clang generates "startup". |
| return symbols.WhereNameMatches('^startup$|^_GLOBAL__') |
| |
| def LargeFiles(self, symbols=None, min_size=50 * 1024): |
| """Lists source files that are larger than a certain size (default 50kb).""" |
| symbols = self._SymbolsArg(symbols) |
| return symbols.GroupedByPath(fallback=None).WherePssBiggerThan( |
| min_size).Sorted() |
| |
| def PakByPath(self, symbols=None): |
| """Groups .pak.* symbols by path.""" |
| symbols = self._SymbolsArg(symbols, pak_only=True) |
| return symbols.WhereIsPak().Sorted().GroupedByPath().Sorted() |