App Size Metrics - Continuous monitoring of App Size, Part 2

Akash Khunt
ProAndroidDev
Published in
5 min readJun 20, 2023

--

Photo by Choong Deng Xiang on Unsplash

In Part 1, we discussed about the importance of continuous monitoring of APK size and started implementation of Github Action workflow where the first job was Generate builds for both base and merge branches. In this post we’re going to implement the second job i.e. Generate the size diff report of the same workflow.

Creating Python Script (to generate the size diff report)

This script can itself be divided into following parts:

  • Setup
  • Generate dictionary - Component category to size mapping
  • Generate HTML report - Use the dictionaries generated above to create a human readable HTML output in tabular format

Setup phase

compare_apks.py - Setup phase
  • Line 2 & 3 - Here we’re parsing the arguments passed while executing the script
  • Line 5 & 6 - We append .apk suffix to the above parsed arguments
  • Line 9 - This location will be dependent on the GHA runner you’re using. This can be made dynamic based on OS check.
  • Line 15 & 16 - Here we invoke get_apk_components function to generate the dictionaries having category name (i.e. Native libraries (arm64-v8a), Classes, Resources, etc) to size mapping.
  • Line 18 - Here we invoke generate_size_diff_html function which will generate the HTML report comparing the size difference between different categories.

Generate dictionary phase

compare_apks.py - Dictionary Build phase

In this phase we’re going to use apk_1_name & apk_2_name generated in Setup phase.

  • Line 32–37 - Here we define a function execute_command, whose sole responsibility is to execute the shell command and return the decoded result.
  • Line 40–44 - Here we update the component dictionary value (i.e. size) in case the provided key i.e. (category name) is already present or add a new entry in case the key is absent.
  • Line 3 - Here we build the apkanalyzer command to get the list of all the files bundled into the apk along with their download size. In case you want to read more about different arguments that you can pass, you can refer this. It took me while to produce the proper command 😅.
  • Line 5 - Here we invoke execute_command with the command generated in Line 3. The output of this command should look like below where each line contains file download size in bytes, “\t” separator, & file name.
apkanalyzer command output example
  • Line 6 - Split the files_with_size_string with new line character and store it in files_with_size_list.
  • Line 10 - Here we start looping through each item present in files_with_size_list.
  • Line 11 - Here we further split each item present in files_with_size_list using ‘\t’.
  • Line 14 - Here we check if the output from Line 11 resulted in a list of exactly 2 items (i.e. file_size & file_name) and file_name is atleast longer than 1 character. This is to filter invalid entries.
  • Line 18–27 - Here we add/update the value of each dictionary entry (i.e. Native libraries (arm64-v8a), Classes, Resources, etc) based on file_name matching criteria. NOTE: This step should be configured based on how you want to categorise your size diff report.

We‘ll be running get_apk_components funtion for both of the apks and end up with component_1 & component_2 dictionaries as mentioned in Setup phase.

Generate HTML report phase

compare_apks.py - Generate HTML report phase

In this phase we’re going to generate an HTML table comparing the size of each dictionary entries.

  • Line 25–31 - Here we format the size (of dictionary entries and not individual files) from bytes to KB/MB. In case the size is less than a KB then it’s considered as 0KB.
  • Line 34–37 - Based on the size argument (i.e. size diff of same kind of entry in both the dictionaries), we add 🟢 (for size reduction) or 🔴 (for size increase) indicator.
  • Line 40–43 - Calculate overall apk download size using apkanalyzer command.
  • Line 3–6 - Here we add HTML body content with some text and table row containing Component, Base, Merge & Diff items.
  • Line 9–12 - Here we iterate through the entries of component_1 & component_2 dictionaries and add an entry to the table row.
  • Line 15&16 - Here we invoke apk_size function to generate the download file size of both base and merge apks.
  • Line 18 - Add one final entry to our size diff table containing the total download size comparison between the base and merge apks.
  • Line 21 - We write the generated HTML to apk_size_diff_report.html file which we will upload for use in the final job i.e. Add the size diff report as a PR comment.

Finally the whole script should look like below:

Python script to compare size contribution from high level components

Note: You’ve to put this script in .github/scripts/ directory to make the following job run.

Since the apk size compare script is now ready we can start adding second job to our existing workflow that we created previously.

Job 2: Generate the size diff report

Size Metrics workflow with only size_diff_report job

To focus only on this job we’ve omitted top-level config as well as the contents of build job.

Line 7–8 - Here we’ve defined the size_diff_report_file environment variable as we’re going to use it in this as well as next job. On Line 17 we define dependency on previous build job using needs config, this will ensure that this job will run only if build job gets completed successfully.

Steps:

  1. Checkout the code
  2. Download head/merge apk that we uploaded in build job
  3. Download base apk that we uploaded in build job
  4. Execute compare_apks.py script which will generate apk_size_diff_report.html file.
  5. Upload the apk_size_diff_report.html for consumption in next job i.e. Add the size diff report as a PR comment.

Job 3: Add the size diff report as a PR comment

Size Metrics workflow with only size_diff_report job

To focus only on this job we’ve omitted top-level config as well as the contents of both build & size_diff_report jobs.

This is going to be smallest as well as simplest job all 3 jobs as we’re just going to download the size diff report file and then use it’s content to add a PR comment.

On Line 22 we define dependency on previous size_diff_report job using needs config, this will ensure that this job will run only if size_diff_report job gets completed successfully.

Steps:

  1. Download the apk_size_diff_report.html file that we generated in previous job.
  2. Here we first parse the content of the apk_size_diff_report.html file to a string and then add it as PR comment to increase the PR reviewer’s visibility on the apk size impact.

Whole workflow file should look like below:

Complete Size Metrics workflow

I hope your team is also able to use this workflow (or maybe an improved version 🙂) as a part of your CI pipeline to give you better understanding of how your changes/features are affecting the apk size.

Reference Material Links and Credits:

Hope you liked reading the article. Please feel free to reach me on Twitter or LinkedIn. Thank You!

--

--