Faster Jetpack Compose View interop with App Startup and baseline profile | by Sagar Begale | Android Developers | Nov, 2022 | Tech Ify

Posted on

Jetpack Compose is designed to be interoperable with an current View-based utility. This lets you take an incremental strategy to migrating your current app’s consumer interface to Compose.

Whereas your utility is in the midst of migration, and hasn’t but Composable on the house or touchdown display, customers could expertise crashes when navigating to a display created with Compose. It’s because compose library is loaded solely when first used. There’s a workaround that has been floating round so as to add a composable pixel on the house/touchdown display. This answer ensures that Compose parts are warmed up earlier than use. We don’t advocate taking this strategy, as making use of it in your utility ends in code that doesn’t contribute to the implementation of your operate and might result in unexpected errors. Relatively, we advocate a mix of the applying startup library and customized reference profiles to resolve the crash challenge. We’ll evaluate and visualize how the mixture can assist enhance utility efficiency.

Baseline profiles assist enhance utility launch and runtime efficiency of Android purposes. Primary profiles are a listing of lessons and strategies included in an APK. They’re utilized by the Android Runtime (ART) throughout utility set up to precompile crucial paths into machine code. This can be a type of Profile Guided Optimization (PGO) that permits purposes to optimize startup, cut back crashes, and enhance efficiency for finish customers by lowering the quantity of code that should be compiled Simply-In-Time (JIT).

Jetpack Compose is distributed as a library. This permits for frequent updates to Compose and compatibility with older variations of Android. However distributing as a disaggregated library comes at a value; libraries have to be loaded when the app begins and interpreted simply in time when the performance is required (for extra particulars, see Why it is best to all the time efficiency check Compose at launch). This could result in an extended app startup time or crash each time the app makes use of a library operate for the primary time. To resolve this challenge, Compose supplies a reference profile to construct Compose forward of time when the app is put in. Most often, the default reference profile supplied by Compose is ample to offer nice efficiency. However customizing the profile based mostly on widespread consumer interactions together with your app usually yields higher outcomes.

To investigate this efficiency enchancment, we wrote some Macrobenchmark exams and measured efficiency on the pattern Sunflower utility. The app has been partially migrated to Compose and doesn’t have Composable on the house or touchdown display.

Sunflower app screenshots showing the flow.  One of the screens is built with RecyclerView with each item embedded in Compose.  Another screen is built into Compose and uses AndroidViewBinding to interact with the View.

For this efficiency evaluation, we will likely be interacting with three screens of the applying:

  • the House display which is constructed with a View-based format and has no Composables.
  • the plant listing The display is constructed with RecyclerView and every factor throughout the view is constructed with Compose. It makes use of the ComposeView to host the Compose content material.
  • the plant particulars A display that’s created with Compose and makes use of AndroidViewBinding to create and work together with Android format assets.

The Sunflower utility code has a BaselineProfileGenerator class that creates a baseline profile. We ran the check and created a customized reference profile targeted on these Essential Consumer Journeys (CUJs). This profile is out there throughout the baseline-prof.txt file underneath the main font set. In comparison with the default baseline profile supplied by Compose, the customized baseline profile reveals efficiency enhancements. Let’s check out the check outcomes for a few eventualities:

  • [Scenario 1]From the house display, the consumer navigates to the Plant Record display that’s partially built-in into Compose. Benchmarking is out there within the PlantListBenchmarks class.

Macrobenchmark runs your check a number of instances and outputs the outcomes as a statistical distribution. The distribution is represented in percentiles. P50P99. The next had been the outcomes after we ran the benchmark exams:

For the information proven within the desk above, P50 for CompilationMode.None signifies that 50% of the frames had been rendered sooner than 7.1 milliseconds.

  • [Scenario 2] The consumer navigates to a display fully constructed with Compose and makes use of the AndroidViewBinding to work together with the TextView. Benchmarking is out there within the PlantDetailBenchmarks class. The next had been the outcomes after we ran the benchmark exams:

Word: Benchmark exams had been run on Samsung Galaxy Fold, your benchmark outcomes could present completely different numbers, however the total efficiency impression must be comparable.

while you look carefully P99 numbers, you’ll discover vital enhancements. These outliers are sometimes what trigger crashes.

To additional enhance utility efficiency, we will use the applying startup library to heat up Compose parts earlier than they’re truly used. Let’s strive it out and see what we discover out.

The appliance startup library supplies a structured solution to initialize parts at utility startup. With the app startup library, you’ll be able to heat up the Compose library throughout app startup.

Observe these steps so as to add the Compose initializer utilizing the applying startup library:

  • To make use of Jetpack startup in your utility, add the dependency on the startup runtime in your utility’s configuration. construct.gradle proceedings.

To heat up the Compose element, create a brand new ComposeInitializer class as proven within the following code snippet.

ProcessLifecycleInitializer ensures that the Compose library heats up solely when no less than one exercise goes to be seen.

Initializing the ComposeView on this method is not going to add the content material to the view hierarchy, however it nonetheless helps to initialize the Compose element.

  • To make ComposeInitializer discoverable by App Startup, go to AndroidManifest.xml file in your challenge. add a <meta-data> low entry InitializationProvider manifest entry as proven within the following code:

InitializationProvider is a particular content material supplier that helps uncover and name the element initializer you simply outlined.

  • Rebuild and replace the reference profile to account for the modifications at startup. The benchmark profile generator is a part of the macrobenchmark module. You simply must run the startPlantListPlantDetail check BaselineProfileGenerator class.
  • Rerun the macrobenchmark exams from the PlantListBenchmarks Y PlantDetailBenchmarks class.

Here is what we found for every of the above eventualities:

  • [Scenario 1]From the house display, the consumer navigates to the plant listing display.

While you look carefully, for the display that’s partially constructed with Compose, the outliers appear to have an enhancement of ~21%. Typically it’s the outlier frames that trigger the crash.

  • [Scenario 2] The consumer navigates to the Plant Particulars display.

There are ~27% proportion enchancment in outliers.

In each instances, including the applying startup initializer improved efficiency, particularly for outliers in P99.

Right here is the hyperlink to entry the code on GitHub.

Now the query is, must you all the time add the applying startup library for such eventualities? Is it relevant to all of your initiatives? Nicely, earlier than making such a choice, we strongly advocate that you just:

  1. Write benchmark exams and measure utility efficiency.
  2. implement the modifications
  3. Rerun your exams to see if efficiency has truly improved.

This implementation strategy would make it easier to in the long term to evaluate whether or not the solutions are actually relevant to your utility. Let statistical knowledge drive your deployment choices to enhance efficiency.

  • All the time add a baseline profile, no matter whether or not you want the applying launcher library.
  • The mix of the customized baseline profile and the app launcher library yields higher efficiency outcomes when your app has no composable parts on the house or touchdown display, and the consumer navigates to a display that’s partially or totally constructed with Compose.
  • As an alternative of including Composable to the splash/touchdown display for efficiency causes (and never design alternative), you should utilize the app launcher library to heat up Compose parts.
  • Simply because somebody suggests it doesn’t suggest you must observe that recommendation.. Write Macrobenchmark exams to confirm if the applying launcher library truly improves the efficiency of your utility. Let statistical knowledge drive your deployment selections to make sure they end in improved efficiency.

Thanks Ben Trengrove, Florina Mutenescu, Ben Weiss, Ryan Mentley, and Rahul Ravikumar for serving to with revisions.

Faster Jetpack Compose <-> View interop with App Startup and baseline profile | by Sagar Begale | Android Developers | Nov, 2022