Mastering Dart & Flutter DevTools — Part 3: App Size Tool

Flutter Gems
14 min readDec 28, 2022

by Ashita Prasad (LinkedIn, Twitter), fluttergems.dev

This is the third article in the “Mastering Dart & Flutter DevTools” series of in-depth articles. In this article, you will learn how to analyze an app’s size using the DevTools’ App Size Tool on a real-world open-source app — Wonderous. In case you want to check out any other article in this series, just click on the link provided below:

Installation and setup of DevTools is a pre-requisite for this part. In case you missed it, the installation and setup details are provided in detail here.

As the number of apps are growing at a rapid pace (~100K new apps/month), they are competing for the most sought after digital real estate — A User’s Device Storage. Thus, an App’s size has become a major factor (lower is better!) that can influence the user’s decision to go ahead and download the app. As we add new features to an app, it’s size might increase by a few KBs or MBs which is perfectly fine. But, any significant increase in size may deter people from downloading the app. This is where the DevTools’ App size tool comes to our rescue and helps us in analyzing the size of our app in detail.

In this article we will walk through the App Size Tool and understand it better by analyzing the Wonderous App.

App Size Tool

DevTools’ App Size Tool helps developers measure and analyze the size of an app. This information is very useful for understanding the impact of an app on the device’s storage.

To better understand how this tool works, we will undertake two scenarios:

  • Scenario #1: Size Analysis — In the first scenario, we will analyze the size of the recently released open-source Flutter App — Wonderous.
  • Scenario #2: Size Difference Analysis— In this scenario, we will compare the size of Wonderous app with a refactored version of the app that replaces the existing state management package with another package.

The entire exercise will be demonstrated using VS Code IDE.

Scenario #1

Let us start with the first scenario where we will perform the size analysis of the Wonderous App.

Step 1: Getting the Source Code

Open the below mentioned repository.👇

GitHub repo for this article

Click on the Green Code button and the Local tab.

Download the source

As mentioned in the image above, you can use any command-line tool or GitHub Desktop to clone the repository.

But, for this exercise let us click on Download ZIP to download the entire source code and extract it.

We now have a local copy of the source in the folder flutter-wonderous-app-master

Step 2: Opening the Project in VS Code

Launch VS Code, open the project folder in VS Code and go to pubspec.yaml file.

Project opened in VS Code

Click on Get Packages to fetch all the packages required for the project. It runs the flutter pub get command.

Click Get Packages
Running pub get

Now, as shown in the image below, click on the infos status bar button. In case TERMINAL tab is missing right click and select ✔Terminal.

Launch Terminal inside VS Code

Click on the TERMINAL tab to access the shell inside VS Code.

Click Terminal
Shell inside VS Code

Step 3: Running the Size Analysis Tool in VS Code Terminal

Compared to other tools that can run in debug or profile mode, App Size Tool requires generation of a unobfuscated release build that contains no debugging overhead and is close to the production version of an app the end user would download and install.

In the VS Code shell shown above, the size analysis tool can be invoked by passing the --analyze-size flag while building the release version using one of the following commands:

  • flutter build apk --analyze-size (any host)
  • flutter build appbundle --analyze-size (any host)
  • flutter build ios --analyze-size (only macos host)
  • flutter build linux --analyze-size (only linux host)
  • flutter build macos --analyze-size (only macos host)
  • flutter build windows --analyze-size (only windows host)

For this exercise we will build an Android App Bundle and perform a size analysis on it by executing the below command:

flutter build appbundle --analyze-size

The following error message will be displayed —

Cannot perform code size analysis when building for multiple ABIs. 
Specify one of android-arm, android-arm64, or android-x64 in the
— target-platform flag.

As there are three main CPU architectures — ARM (android-arm), ARM64(android-arm64), or x86(android-x64) in Android devices, we have to specify the target platform for code size analysis as the compiled binaries differ based on the target platform. The same is true in case you want to perform size analysis while using flutter build apk command.

ARM64 is becoming the standard in newer android devices, so we will choose the target platform as android-arm64 and execute the following command:

flutter build appbundle --analyze-size --target-platform android-arm64

Post execution, the size analysis tool records the size of all resources and packages post code compilation. A summary drill-down of the app size is also displayed and a detailed size analysis is saved in *-code-size-analysis_*.json file.

In our case the code size snapshot was saved in aab-code-size-analysis_01.json file and the full path to the file was displayed (highlighted in the image above).

Step 4: Launching the Size Analysis Tool Page

1. Using VS Code Terminal

In case DevTools is not activated, run the following command in the VS Code terminal:

flutter pub global activate devtools

Now, you can launch the App Size Analysis tool and preload it with the generated size snapshot data directly using the command(s):

flutter pub global run devtools --appSizeBase=aab-code-size-analysis_01.json

2. Using VS Code Status Button

Click on Dart DevTools in the VS Code Status Bar.

Click “Dart DevTools” in the Status Bar

The following page will open in the browser.

DevTools not Connected to any Active Running App

Now, click on the Open app size tool button to open the App Size Tool page as shown in the image below.

Size analysis tab

Right on the top of this page, you can see the two types of size analysis options that are available - Analysis and Diff.

Analysis & Diff Tabs
  • Analysis — Helps you drill-down deeper into a single size information snapshot (file). This will be covered in the current scenario.
  • Diff — This is useful for comparing two size information snapshots. It is used for cases when we want to visualize size changes between two snapshots (old ver. vs new ver.) after performing some app optimization. We will cover it in detail in Scenario #2.

Step 5: Using the App Size Tool

In the current scenario (Scenario #1), we want to perform the size analysis of a single snapshot. So, we will focus on the Analysis tab.

Click Import File and select the aab-code-size-analysis_01.json file by navigating to the path displayed on the terminal.

Select the size analysis file

After selecting the file, just click on Analyze Size to open the size analysis of the snapshot as shown in the image below.

Size analysis file is now loaded

You can immediately witness a hierarchical tree visualization (Treemap) as shown below.

Tree-map

Below this Tree-map, the snapshot size data is also available in the form of an explorer view table.

Explorer View

The current root node is Root which is also the complete app bundle whose size is 50.6 MB.

You can click on the node (Root) and expand it to view the size of child nodes.

Size of Root node and immediate children or Root

These nodes (classes/folders/libraries) are Level 1 child nodes and they are shown on the treemap just below the breadcrumb navigator.

Root Node -> Level 1 node -> Level 2 node

In the figure above, as the base node (Level 1 child) represents 99.51% of its parent node’s size, so it occupies almost the entire scale.

Level 2 child nodes are the children of Level 1 nodes and are shown on the tree-map just below their parent node. These nodes are presented in a 2D map where the rectangular area occupied by a node is proportional to its size (in bytes). For example, base has the following children — assets , lib , dex , res , and so on ..

As the size of assets is 36.9 MB, it covers approx. 70% of the area.

If you click on any Level 1 or Level 2 node on the treemap, it is made the new root so that you can perform a deeper analysis of size contributors.

Let us try this out. In the tree-map,

  • Go ahead and click on assets.
  • Then click on flutter_assets.
  • Now, click on assets.

The changes are immediately reflected in the tabular view as shown in the image below, where images and fonts are the immediate children of assets (new root).

Tabular View with assets as its root

As shown in the image below, the tree-map is also updated, with assets [36.8 MB] as its new root node. images and fonts (Level 1 nodes) are the immediate children of this new root node. And the children of images and fonts nodes are presented as a 2D tree-map below their parents.

Updated tree-map with assets as its new root

Upon performing a broad-level inspection of the above tree-map, we can observe that the size of the nodes is in the following decreasing order — petra, _commom, machu_pichu, taj_mahal, and so on ..

Let us go ahead and click on petra to view the image files inside it that have significantly larger size. The results are shown in the image below.

Root: petra

If we look at the current scenario, assets (images and fonts) contribute to more that 70% of the app size.

Size Reduction Strategies

In almost any app, assets are always the primary size contributors. To reduce their impact on app size, you can follow some size reduction strategies such as:

  1. Removing unused assets.
  2. Optimizing (compressing) PNG / JPG images.
  3. Using modern animation file formats (lottie, rive) compared to GIFs.
  4. Not pre-bundling font files and using packages like google_fonts which fetches a specified font over the internet when the app runs for the first time. This font is subsequently cached in the device.

In case the size footprint of code-base is large, you should:

  1. Remove unused code.
  2. Split large classes that are difficult to optimize into smaller classes that will make it easier to identify and remove unnecessary code.
  3. Obfuscate your app to dramatically reduce code size.
  4. Choose efficient 3rd party packages that have a low size footprint. We will explore this point further in Scenario #2.

By following these suggestions, you can significantly reduce the size of your mobile app and improve its performance.

Dominator Tree or Call Graph

The Dominator Tree or Call Graph is another section of the App Size tool. One can switch between both the modes using the Toggle Switch button as shown below.

Dominator Tree <-> Call Graph

A dominator tree (shown below) is useful for understanding the root cause of existence of a piece of code in the application, where the package tree is arranged in such an order that each node’s children are those nodes that are immediately dominated by the parent.

Dominator Tree of Wonderous App

For example, in the dominator tree of the wonders app (shown above), the package:url_launcher (child) is dominated by package:youtube_player_iframe (parent), as all paths to package:url_launcher goes only through package:youtube_player_iframe .

In case you want to get a better idea of the dependencies between the pieces of codes (packages) in order to understand why some code is included, Call graph can be used.

Call Graph of package youtube_player_iframe

For example, in the above Call Graph of package:youtube_player_iframe, we can observe that the wonders package calls it and it in turn calls package:url_launcher , package:flutter_inappwebview and other packages mentioned on the right.

With this we have come to an end of Scenario #1 where we performed a Size Analysis of the Wonderous app. Along with getting familiar with the usage of that Size Analysis Tool, we also got familiar with the various parts of its interface. Finally, we learnt various size reduction strategies that can help us reduce the size of the app.

Now, let us proceed with Scenario #2.

Scenario #2

In this scenario, we will be using the Diff Tab in the App Size Tool. This tab is useful when you want to visualize the difference in size between two snapshots — old version vs new size-optimized version.

In our case we will compare the following two size information snapshots:

  • Snapshot #1 — The size information snapshot created in Scenario #1 of the Wonderous app.
  • Snapshot #2 — The size information snapshot of a refactored version of the wonderous app that uses another 3rd party state management package instead of provider package used in the original app.

It can be seen in the image below, how the Diff tab requires two snapshots to be uploaded for comparison.

DIff Tab

Let us clone the repo that has a refactored version of Wonderous app code. 👇

You can follow the same instructions for this project as provided in Scenario #1’s Step 1: Getting the Source Code and Step 2: Opening the Project in VS Code.

If you take a look at the pubspec.yaml file, you can see that the 3rd party package provider has been removed and the package fluttery_framework has been included in its place.

Step 3: Running the Size Analysis Tool in VS Code Terminal

Execute the build command along with size analysis flag

flutter build appbundle --analyze-size --target-platform android-arm64

Size Analysis of Wonderous Fork

The new size information snapshot file aab-code-size-analysis_02.json is generated.

Now, launch the App Size tool using the instruction provided in Scenario #1’s Step 4: Launching the Size Analysis Tool Page.

Step 5: Using the App Size Tool

Click on the Diff Tab.

Import the old file (aab-code-size-analysis_01.json) and the new file (aab-code-size-analysis_02.json).

Import both the files

Click Analyze Diff button to generate a difference tree-map as shown below.

Diff tree-map

The colour of the node indicates the change in size. Green colour indicates that there has been an increase in size, whereas red indicates a decrease in size. In this case ~0.5 MB increase has been detected in the refactored code.

Let us click on the libapp.so node to view the cause of size changes due to the changes made in the app code.

Root: libapp.so

It appears the package:dbus, package:fluttery_framework and package:state_extended are some of the major contributors to this increase in size.

We can understand that using a new package will lead to addition code size, so package:fluttery_framework and its dependency package:state_extended is expected, but where did this package:dbus come from that is causing ~30% size increase?

Let us click on package:dbus and check the Dominator tree as shown below:

Dominator Tree of Diff

As shown above, package:dbus is being dominated by package:nm which in turn is dominated by package:connectivity_plus_linux.

Let us now use the call graph to check who is calling the package package:connectivity_plus_linux.

package: connectivity_plus Call Graph

Turns out there is only one package that is calling package:connectivity_plus_linux and that is package:fluttery_framework.

In Scenario #2, we saw how App Size Tool’s Diff tab can be used to perform investigation of size changes between two snapshots. In this exercise, we also observed how replacing an existing package with a new 3rd party package fluttery_framework led to an increase in the app size. Thus, App Size Tool is also a very useful tool for assessing the size impact of 3rd party packages in your app.

In this article, we took a deep dive into the App Size Tool and performed a Wonderous App case study using two scenarios:

  • In Scenario #1, we analyzed how assets contributed to a major portion of the app size. We also went through the various strategies that can help you reduce the size of your app.
  • In Scenario #2, we compared a refactored version of the Wonderous app with the original. Using the various features of the App Size Tool, we performed an in-depth investigation and first-hand witnessed how 3rd party packages have a direct impact on the app’s size.

We would definitely love to hear about your experience with the App Size Tool and any suggestions in the comments. In case you faced any issues while going through this exercise or while running the tool for your project, please feel free to mention it in the comments and we can definitely take a look at it.

In the remaining articles of this series, we have discussed other tools available in the DevTools suite that can help you build high-performance Flutter apps. Don’t forget to check out the links below to navigate to the tool you want to learn next:

Source Code(s) used in this article:

Special thanks to Kamal Shree (GDE — Dart & Flutter) for reviewing this article.

--

--

Flutter Gems

Maintained by Ashita Prasad, Flutter Gems is a curated package guide for Flutter ecosystem. Visit https://fluttergems.dev