| OLD | NEW |
| 1 # Tools for analyzing Chrome's binary size | 1 # Tools for Analyzing Chrome's Binary Size |
| 2 | 2 |
| 3 # diagnose_bloat.py | 3 These currently focus on Android and Linux platforms. However, some great tools |
| 4 for Windows exist and are documented here: |
| 5 |
| 6 https://www.chromium.org/developers/windows-binary-sizes |
| 7 |
| 8 There is also a dedicated mailing-list for binary size discussions: |
| 9 |
| 10 https://groups.google.com/a/chromium.org/forum/#!forum/binary-size |
| 11 |
| 12 [TOC] |
| 13 |
| 14 ## diagnose_bloat.py |
| 4 | 15 |
| 5 Determine the cause of binary size bloat between two commits. Works for Android | 16 Determine the cause of binary size bloat between two commits. Works for Android |
| 6 and partially works for Linux (crbug/717550). | 17 and Linux (although Linux symbol diffs have issues, as noted below). |
| 7 | 18 |
| 8 ## Example Usage: | 19 ### How it Works |
| 20 |
| 21 1. Builds multiple revisions using release GN args. |
| 22 |
| 23 * Default is to build just two revisions (before & after commit) |
| 24 * Rather than building, can fetch build artifacts from perf bots (`--cloud`) |
| 25 |
| 26 1. Measures all outputs using `resource_size.py` and `supersize`. |
| 27 1. Saves & displays a breakdown of the difference in binary sizes. |
| 28 |
| 29 ### Example Usage |
| 9 | 30 |
| 10 # Build and diff HEAD^ and HEAD. | 31 # Build and diff HEAD^ and HEAD. |
| 11 tools/binary_size/diagnose_bloat.py HEAD | 32 tools/binary_size/diagnose_bloat.py HEAD |
| 12 | 33 |
| 13 # Diff OTHERREV and REV using downloaded build artifacts. | 34 # Diff OTHERREV and REV using downloaded build artifacts. |
| 14 tools/binary_size/diagnose_bloat.py REV --reference-rev OTHERREV --cloud | 35 tools/binary_size/diagnose_bloat.py REV --reference-rev OTHERREV --cloud |
| 15 | 36 |
| 16 # Build and diff all contiguous revs in range OTHERREV..REV for src/v8. | 37 # Build and diff all contiguous revs in range OTHERREV..REV for src/v8. |
| 17 tools/binary_size/diagnose_bloat.py REV --reference-rev OTHERREV --subrepo v
8 --all | 38 tools/binary_size/diagnose_bloat.py REV --reference-rev OTHERREV --subrepo v
8 --all |
| 18 | 39 |
| 19 # Display detailed usage info (there are many options). | 40 # Display detailed usage info (there are many options). |
| 20 tools/binary_size/diagnose_bloat.py -h | 41 tools/binary_size/diagnose_bloat.py -h |
| 21 | 42 |
| 22 # Super Size | 43 ## Super Size |
| 23 | 44 |
| 24 Collect, archive, and analyze Chrome's binary size. | 45 Collect, archive, and analyze Chrome's binary size. |
| 46 Supports Android and Linux (although Linux |
| 47 [has issues](https://bugs.chromium.org/p/chromium/issues/detail?id=717550)). |
| 25 | 48 |
| 26 ## "archive" | 49 `.size` files are archived on perf bots as well as on official builders. |
| 27 | 50 |
| 28 Collect size information and dump it into a `.size` file. Mainly consists of | 51 ### Technical Details |
| 29 symbol information parsed from a linker .map file. | |
| 30 | 52 |
| 31 ### Example Usage: | 53 #### What's in a .size File? |
| 32 | 54 |
| 33 Note: Supersize on Linux has known deficiencies (crbug/717550). | 55 `.size` files are gzipped plain text files that contain: |
| 34 | 56 |
| 35 # Android: | 57 1. A list of .so section sizes, as reported by `readelf -S`, |
| 36 # Googlers: | 58 1. Metadata (GN args, filenames, timestamps, git revision, build id), |
| 37 gn gen out/Release --args='is_official_build=true symbol_level=1 is_chrome_b
randed=true target_os="android"' | 59 1. A list of symbols, including name, address, size, and associated `.o` / `.cc` |
| 38 # Non-Googlers: | 60 files. |
| 39 gn gen out/Release --args='is_official_build=true symbol_level=1 exclude_unw
ind_tables=true ffmpeg_branding="Chrome" proprietary_codecs=true target_os="andr
oid"' | 61 |
| 40 ninja -C out/Release -j 1000 libchrome.so | 62 #### How are Symbols Collected? |
| 41 tools/binary_size/supersize archive chrome.size --elf-file out/Release/lib.u
nstripped/libchrome.so -v | 63 |
| 64 1. Symbol list is Extracted from linker `.map` file. |
| 65 |
| 66 * Map files contain some unique pieces of information, such as |
| 67 `** merge strings` entries, and the odd unnamed symbol (which map at least |
| 68 lists a `.o` path). |
| 69 |
| 70 1. `.o` files are mapped to `.cc` files by parsing `.ninja` files. |
| 71 |
| 72 * This means that `.h` files are never listed as sources. No information about |
| 73 inlined symbols is gathered. |
| 74 |
| 75 1. Symbol aliases (when multiple symbols share an address) are collected from |
| 76 debug information via `nm elf-file`. |
| 77 |
| 78 * Aliases have the same address and size, but report their `.pss` as |
| 79 `.size / .num_aliases`. |
| 80 |
| 81 1. Paths for shared symbols (those found in multiple `.o` files) are collected |
| 82 by running `nm` on every `.o` file. |
| 83 |
| 84 * Shared symbols do not store the complete list of `.o` files. Instead, the |
| 85 common ancestor is computed and stored as the path (along with a |
| 86 `{shared}/count` suffix). |
| 87 |
| 88 #### What Other Processing Happens? |
| 89 |
| 90 1. Path normalization: |
| 91 |
| 92 * Prefixes are removed: `out/Release/`, `gen/`, `obj/` |
| 93 * Archive names made more pathy: `foo/bar.a(baz.o)` -> `foo/bar.a/baz.o` |
| 94 |
| 95 1. Name normalization: |
| 96 |
| 97 * `(anonymous::)` is removed from names. |
| 98 * `vtable for FOO` -> `Foo [vtable]` |
| 99 * Names split into: `name`, `template_name`, `full_name` |
| 100 |
| 101 1. Clustering |
| 102 |
| 103 * Compiler optimizations can cause a symbol to be broken into multiple smaller |
| 104 symbols. Clustering puts them back together. |
| 105 |
| 106 1. Diffing |
| 107 |
| 108 * Some heuristics for matching up before/after symbols. |
| 109 |
| 110 ### Usage: `archive` |
| 111 |
| 112 Collect size information and dump it into a `.size` file. |
| 113 |
| 114 *** note |
| 115 **Note:** Refer to |
| 116 [diagnose_bloat.py](https://cs.chromium.org/search/?q=file:diagnose_bloat.py+gn_
args) |
| 117 for list of GN args to build a Release binary. |
| 118 *** |
| 119 |
| 120 Example: |
| 121 |
| 122 ninja -C out/Release -j 1000 apks/ChromePublic.apk |
| 123 tools/binary_size/supersize archive chrome.size --apk-file out/Release/apks/
ChromePublic.apk -v |
| 42 | 124 |
| 43 # Linux: | 125 # Linux: |
| 44 LLVM_DOWNLOAD_GOLD_PLUGIN=1 gclient runhooks # One-time download. | 126 LLVM_DOWNLOAD_GOLD_PLUGIN=1 gclient runhooks # One-time download. |
| 45 # Googlers: | |
| 46 gn gen out/Release --args='is_official_build=true symbol_level=1 is_chrome_b
randed=true' | |
| 47 # Non-Googlers: | |
| 48 gn gen out/Release --args='is_official_build=true symbol_level=1 exclude_unw
ind_tables=true ffmpeg_branding="Chrome" proprietary_codecs=true' | |
| 49 ninja -C out/Release -j 1000 chrome | 127 ninja -C out/Release -j 1000 chrome |
| 50 tools/binary_size/supersize archive chrome.size --elf-file out/Release/chrom
e -v | 128 tools/binary_size/supersize archive chrome.size --elf-file out/Release/chrom
e -v |
| 51 | 129 |
| 52 ## "html_report" | 130 ### Usage: `html_report` |
| 53 | 131 |
| 54 Creates an interactive size breakdown (by source path) as a stand-alone html | 132 Creates an interactive size breakdown (by source path) as a stand-alone html |
| 55 report. | 133 report. |
| 56 | 134 |
| 57 ### Example Usage: | 135 Example: |
| 58 | 136 |
| 59 tools/binary_size/supersize html_report chrome.size --report-dir size-report
-v | 137 tools/binary_size/supersize html_report chrome.size --report-dir size-report
-v |
| 60 xdg-open size-report/index.html | 138 xdg-open size-report/index.html |
| 61 | 139 |
| 62 ## "console" | 140 ### Usage: `console` |
| 63 | 141 |
| 64 Starts a Python interpreter where you can run custom queries. | 142 Starts a Python interpreter where you can run custom queries. |
| 65 | 143 |
| 66 ### Example Usage: | 144 Example: |
| 67 | 145 |
| 68 # Prints size infomation and exits (does not enter interactive mode). | 146 # Prints size infomation and exits (does not enter interactive mode). |
| 69 tools/binary_size/supersize console chrome.size --query='Print(size_info)' | 147 tools/binary_size/supersize console chrome.size --query='Print(size_info)' |
| 70 | 148 |
| 71 # Enters a Python REPL (it will print more guidance). | 149 # Enters a Python REPL (it will print more guidance). |
| 72 tools/binary_size/supersize console chrome.size | 150 tools/binary_size/supersize console chrome.size |
| 73 | 151 |
| 74 ## "diff" | 152 ### Usage: `diff` |
| 75 | 153 |
| 76 A convenience command equivalent to: `console before.size after.size --query='Pr
int(Diff(size_info1, size_info2))'` | 154 A convenience command equivalent to: `console before.size after.size --query='Pr
int(Diff(size_info1, size_info2))'` |
| 77 | 155 |
| 78 ### Example Usage: | 156 Example |
| 79 | 157 |
| 80 tools/binary_size/supersize diff before.size after.size --all | 158 tools/binary_size/supersize diff before.size after.size --all |
| 81 | 159 |
| 82 # Roadmap for Super Size: | 160 ### Roadmap |
| 83 | 161 |
| 84 Tracked in https://crbug.com/681694 | 162 Tracked in https://crbug.com/681694 |
| 85 | 163 |
| 86 1. Better Linux support (clang/lld). | 164 1. [Better Linux support](https://bugs.chromium.org/p/chromium/issues/detail?id=
717550) (clang+lld+lto vs gcc+gold). |
| 87 1. More `archive` features: | 165 1. More `archive` features: |
| 88 | 166 |
| 89 * Find out more about 0xffffffffffffffff addresses, and why such large | 167 * Find out more about 0xffffffffffffffff addresses, and why such large |
| 90 gaps exist after them. | 168 gaps exist after them. ([crbug/709050](https://bugs.chromium.org/p/chromium/
issues/detail?id=709050)) |
| 169 * Collect .pak file information (using .o.whitelist files) |
| 91 * Collect java symbol information | 170 * Collect java symbol information |
| 92 * Collect .pak file information (using .o.whitelist files) | |
| 93 * Collect .apk entry information | 171 * Collect .apk entry information |
| 94 | 172 |
| 95 1. More `console` features: | 173 1. More `console` features: |
| 96 | 174 |
| 97 * Template Symbols - shows when templates lead to code bloat. | |
| 98 * Duplicate Symbols - shows when statics in headers are an issue. | |
| 99 * Overloaded Symbols - shows when overloads are excessive. | |
| 100 * Per-class / namespace size (no way to distinguish class vs namespace). | |
| 101 * CSV output (for pasting into a spreadsheet). | 175 * CSV output (for pasting into a spreadsheet). |
| 102 * Make Where\*() methods filter recursively on already-grouped SymbolGroups. | 176 * Add `SplitByName()` - Like `GroupByName()`, but recursive. |
| 103 * Add symbols.SplitByNamespace() - which will be like GroupByNamespace, but be | 177 * A canned query, that does what ShowGlobals does (as described in [Windows Bi
nary Sizes](https://www.chromium.org/developers/windows-binary-sizes)). |
| 104 recursive. | 178 * Show symbol counts by bucket size. |
| 179 |
| 180 * 3 symbols < 64 bytes. 10 symbols < 128, 3 < 256, 5 < 512, 0 < 1024, 3 < 20
48 |
| 105 | 181 |
| 106 1. More `html_report` features: | 182 1. More `html_report` features: |
| 107 | 183 |
| 108 * Break down by other groupings (Create from result of SplitByNamespace()) | 184 * Able to render size diffs (tint negative size red). |
| 185 * Break down by other groupings (Create from result of `SplitByName()`) |
| 109 * Render as simple tree view rather than 2d boxes | 186 * Render as simple tree view rather than 2d boxes |
| 110 | 187 |
| 111 1. Integrate with `resource_sizes.py` so that it tracks size of major | 188 1. Integrate with `resource_sizes.py` so that it tracks size of major |
| 112 components separately: chrome vs blink vs skia vs v8. | 189 components separately: chrome vs blink vs skia vs v8. |
| 113 1. Add dependency graph info, perhaps just on a per-file basis. | 190 1. Add dependency graph info, perhaps just on a per-file basis. |
| 191 |
| 192 * No idea how to do this, but Windows can do it via `tools\win\linker_verbose_
tracking.py` |
| OLD | NEW |