
The new Compose integration has sparked a lot of internal discussion regarding the app’s performance. One of the things we at NordVPN do is to integrate the Compose Compiler plugin in our day-to-day development process, which helps us improve our code. In this blog post, we explain what the Compose Compiler plugin is, how it works, and how we use it at NordVPN.
What problems did we have?
When working with Jetpack Compose, we encountered performance issues related to the stability of composable functions. Our primary goal in working with composable functions was to make them as stable as possible, or “skippable” in Compose terminology. In this context, “skippable” means that if a composable function is recomposed and its parameters haven’t changed since the previous recomposition, Compose will skip the function and reuse the previous values.
With Compose, we can see significant performance improvements because even minor improvements can reduce recomposition count levels throughout the app. To assess the stability of composable functions, we can leverage the Compose Compiler plugin.
The Compose Compiler plugin
Compose Compiler is a plugin that can generate reports and metrics for components or code written in Compose. These reports provide detailed insights into the behavior of our Compose code. The plugin was added in version 1.2 of the Compose library.
With this detailed insight, we can begin making improvements to our code.
How does it work?
The Compose Compiler plugin is a Gradle task that generates reports for composable code within a module. It assesses the stability of the code, offering the flexibility to run it locally or in a CI pipeline when necessary.
It is recommended to generate the report in Release builds.
To ensure that the plugin works perfectly, we first need to configure it in the project’s Gradle file.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
The first part of the code generates reports, while the second one generates metrics for those reports.
To run this code, we use the Gradle command as follows:
1
Generating a report on release builds is recommended.
When the execution is completed, it generates a file in the build folder like the one below.

compose_generated_report folder
Where,
*-classes.txt: contains information about classes referenced from a composable function.
*-composables.csv: CSV version of the TXT file
*-composables.txt: contains a detailed output of each Composable.
*-module.json: provides detailed statistics as a comprehensive view.
In our case, we’re primarily focused on the *-composables.txt files and will be working with those.
The image above displays the generated value for only one module. However, for NordVPN, we have multiple UI modules, and each module generates its own compose_metrics folder (that has its Compose code) with all relevant reports included.
Refining the generated report
With all of our modules generating reports, here’s an example of how an individual -composables.txt file can contain multiple blocks of code like:
1
2
3
4
5
6
Each of these files contains numerous functions that exhibit a Kotlin-style code structure. Additionally, each module with Compose code has a dedicated text file. Before delving into the details, let’s take a closer look at the significance of this code:
Restartable: When Compose detects changes in the function inputs, it restarts the function, invoking it again with the updated inputs.
Stable: This parameter in the provided function is stable; if they have not changed, Compose will skip it.
Unstable: This parameter in the provided function is unstable and Compose always recomposes it when the parent is recomposed.
We then merge all the *-composables.txt files into a single text file within our project using a script we’ve created for this purpose. This combined file plays a crucial role in our development process. Let’s see how we utilize it.
How do we use it in our day-to-day development?
At NordVPN, we’ve seamlessly integrated this workflow into our CI pipeline for every pull request we create, ensuring that we merge only stable Compose code (whenever possible) into our main branches.
However, before implementing this process, we conduct a thorough review to ensure that all of our Composable code contains no unnecessary unstable parameters. This proactive step guarantees that when we introduce this to our pull request flow, we initiate with a clean slate.
Let’s take a closer look at the steps in our pull request workflow:
1. Create pull request: The process begins with the creation of a pull request (PR).
2. CI job: A Continuous integration (CI) job is triggered for the current PR if there’s a change in any of the UI modules. The CI job performs several tasks:
a. Generate report: We generate a report on the release branch, which results in the creation of multiple text files in each module containing Compose code.
b. Merge the text files: At this stage, we execute a script that combines these text files, retaining only the functions containing unstable parameters.
c. Create a markdown table: Next, we create a markdown table that lists the function names along with their associated unstable parameters.

Output Markdown table
d. Post comment: We post this markdown table as a comment within the PR. This informs developers about any potential instability introduced in the PR.
e. Fix: If instability issues are identified, we proceed to fix the affected functions and commit the changes.
The entire process is then rerun, and if the unstable parameter issues have been addressed, no further comment will be posted. Any previous comments on the matter can be resolved.

Execution of the CI pipeline
This practice aids us in utilizing the Compose Compiler plugin as a lint check for our Composable code, which maintains coding standards and contributes to improved performance for the NordVPN Android app.
About Version 2 Digital
Version 2 Digital is one of the most dynamic IT companies in Asia. The company distributes a wide range of IT products across various areas including cyber security, cloud, data protection, end points, infrastructures, system monitoring, storage, networking, business productivity and communication products.
Through an extensive network of channels, point of sales, resellers, and partnership companies, Version 2 offers quality products and services which are highly acclaimed in the market. Its customers cover a wide spectrum which include Global 1000 enterprises, regional listed companies, different vertical industries, public utilities, Government, a vast number of successful SMEs, and consumers in various Asian cities.
About NordLayer
NordLayer is an adaptive network access security solution for modern businesses – from the world’s most trusted cybersecurity brand, Nord Security.
The web has become a chaotic space where safety and trust have been compromised by cybercrime and data protection issues. Therefore, our team has a global mission to shape a more trusted and peaceful online future for people everywhere.

