[TOC]
The android-binary-size trybot exists for three reasons:
- To measure and make developers aware of the binary size impact of commits.
- To perform checks that require comparing builds with & without patch.
- To provide bot coverage for building with
is_official_build=true
.
The bot provides analysis using:
- resource_sizes.py: The delta in metrics are reported. Most of these are described in //docs/speed/binary_size/metrics.md.
- SuperSize: Provides visual and textual binary size breakdowns.
- Results are shown under Gerrit's "Checks" tab in the "Info" section.
- What: Checks that normalized apk size increases by no more than 16kb on arm32, and 64kb on high-end arm64.
- Why: To ensure that larger-than-average size changes are understood and intentional.
If your CL shows a large increase in ARM64 size, but not for ARM32, keep in mind:
- ARM32 instructions are ~half the size of ARM64 instructions.
- ARM32 builds are optimized-for-size (
-Os
) and ARM64 optimizes for speed (-O2
).
To create a SuperSize report for ARM64, do so locally via:
tools/binary_size/diagnose_bloat.py --arm64
-
Look at the provided symbol diffs to understand where the size is coming from.
-
See if any of the generic optimization advice is applicable.
-
If you are writing a new feature or including a new library you might want to think about skipping the Android platform and to restrict this new feature/library to desktop platforms that might care less about binary size.
-
If reduction is not practical, add a rationale for the increase to the commit description. It should include:
- A list of any optimizations that you attempted (if applicable)
- If you think that there might not be a consensus that the code your adding
is worth the added file size, then add why you think it is.
- To get a feeling for how large existing features are, refer to go/chrome-supersize(Googlers only).
-
If an auto-roll commit triggered this failure:
- The purpose of blocking large rolls is so that we can have the roll commits annotated with what is causing the large growth, and to ensure teams are aware of large size changes.
- Please include in the roll commit message what is causing the increase, as well as any pointers to discussions / justifications of the size increase.
- If there is a possibility of any follow-up size reductions, please include
Bug:
lines for bugs that will track this work.
-
Add a footer to the commit description along the lines of:
Binary-Size: Size increase is unavoidable (see above).
Binary-Size: Increase is temporary.
Binary-Size: See commit description.
<-- use this if longer than one line.
***note
Note: Make sure there are no blank lines between Binary-Size:
and other
footers.
- What: Checks that the number of Java / Kotlin methods after optimization does not increase by more than 50.
- Why: Ensures that large changes to this metric are scrutinized.
- Look at the bot's "Dex Class and Method Diff" output to see which classes and methods survived optimization.
- See if any of Java Optimization tips are applicable.
- If the increase is from a new dependency, ensure that there is no existing library that provides similar functionality.
- If reduction is not practical, add a rationale for the increase to the commit
description. It should include:
- A list of any optimizations that you attempted (if applicable)
- If you think that there might not be a consensus that the code your adding
is worth the added file size, then add why you think it is.
- To get a feeling for how large existing features are, open the latest [milestone size breakdown] and select "Method Count Mode".
- Add a footer to the commit description along the lines of:
Binary-Size: Added a new library.
Binary-Size: Enables a large feature that was previously flagged.
- What: Checks that all globals named
kVariableName
orVARIABLE_NAME
are in read-only sections of the binary (either.rodata
or.data.rel.do
). - Why: Guards against accidentally missing a
const
keyword. Non-const variables have a larger memory footprint than const ones. - For more context see https://crbug.com/747064.
- Make the symbol read-only (usually by adding "const").
- If you can't make it const, then rename it.
- If the symbol is logically const, and you really don't want to rename it to reveal that it is actually mutable, you can annotate it with the LOGICALLY_CONST macro.
- To check what section a symbol is in for a local build:
ninja -C out/Release obj/.../your_file.o third_party/llvm-build/Release+Asserts/bin/llvm-nm out/Release/.../your_file.o --format=darwin
- Only
format=darwin
shows the difference between.data
and.data.rel.ro
. - You need to use llvm's
nm
only when thin-lto is enabled (whenis_official_build=true
).
- Only
Here's the most common example:
const char * kMyVar = "..."; // A *mutable* pointer to a const char (bad).
const char * const kMyVar = "..."; // A const pointer to a const char (good).
constexpr char * kMyVar = "..."; // A const pointer to a const char (good).
const char kMyVar[] = "..."; // A const char array (good).
For more information on when to use const char *
vs const char[]
, see
//docs/native_relocations.md.
- What: This checks that we don't have Java symbols with "ForTest" in their name in an optimized release APK.
- Why: To prevent shipping unused test-only code to end-users.
- Make sure your ForTest methods are not called and your ForTest variables are not set, in non-test code.
- The check does not care for annotations, it is literally looking at the final release APK searching for symbols with "ForTest" in the name. If your method is verifiably unreachable from any code, R8 should be able to remove it and the check should not fail.
- If your check is failing this could mean that R8 was not able to determine that it cannot be called (i.e. your testing infrastructure is being shipped to our users). For example if a method marked as @CalledByNative calls your ForTest method, the check may fail since R8 cannot remove anything reachable from a @CalledByNative method. If this native method is only used in tests, you can use @CalledByNativeForTesting instead.
- What: Checks that
.pak
file entries that are not translatable strings and are stored compressed. Limit currently set to 1KB. - Why: Compression makes things smaller and there is normally no reason to leaving resources uncompressed.
- Ensure that
compress="false"
is not being used in the.grd
entry for the resource, so that the default behavior ofcompress="gzip"
is triggered (for HTML, JS, CSS, and SVG files).
- What & Why: Learn about these expectation files here.
- The output of the failing step contains the command to run to update the relevant expectation file. Run this command to update the expectation files.
- For help, email [email protected]. Hearing about your issues helps us to improve the tools!
- Not all checks are perfect and sometimes you want to overrule the trybot (for example if you did your best and are unable to reduce binary size any further).
- Adding a "Binary-Size: $ANY_TEXT_HERE" footer to your CL (next to "Bug:")
will bypass the bot assertions.
- Most commits that trigger the warnings will also result in Telemetry alerts and be reviewed by a binary size sheriff. Failing to write an adequate justification may lead to the binary size sheriff filing a bug against you to improve your CL.
- Shows the list of checks that ran grouped by passing and failing checks.
- Read this to know which checks failed the tryjob.
- This is the text diff produced by the supersize tool.
- It lists all changed symbols and for each one, which section it lives in, which source file it came from as well as what is its size before, after and the delta for your CL.
- It also contains a histogram of symbol size deltas.
- You can use this to find which symbols grew and where the binary size impact of your CL comes from.
- Visual representation of the text diff above.
- It shows size deltas per file and directory
- It allows you to filter symbols by type/section/size/etc.