5

How OkCredit Android App improved Cold Startup by 70%

 2 years ago
source link: https://medium.com/okcredit/how-okcredit-android-app-improved-cold-startup-by-70-e02bda4836a8
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

How OkCredit Android App improved Cold Startup by 70%

Good Application startup is critical for a better user experience in Okcredit. Realizing this for the past six months, the team that powers the technology behind our Android app started measuring, profiling, identifying bottlenecks, and improving startup performance. We ended up improving our app startup time by 70% and this is the story of how we did it.

What is the cold startup time?

According to the Android documentation:

A cold start refers to an app’s starting from scratch: the system’s process has not, until this start, created the app’s process. Cold starts happen in cases such as your app’s being launched for the first time since the device booted, or since the system killed the app.

In simple terms, cold startup times are tracked when the app opens from killed state to the app’s first frame completely loads. This is the metric that play console tracks. What is going on with cold startup?

Multiple things are going till the first draw.

  1. Loading and launching the app.
  2. Displaying a preview window for the app immediately after launch.
  3. Creating the app process.
  4. Creating the app object.
  5. Launching the main thread.
  6. Creating the main activity.
  7. Inflating views.
  8. Laying out the screen.
  9. Performing the initial draw.

If you want to deep dive into each phase, we recommend reading this great article series by

.

Measure Measure Measure

We at Okcredit started investing in credible analytics and performance measures first, which enabled us to understand how metrics vary on each release and gather more insights about cold startup. You can check out how we instrument these metrics below the Github repo.

We split down cold startup time into 4 phases and started listing action items for improvements in each phase. After executing each action item we validated the impact after the release. These are those 4 phases

  1. Process Fork to Content Provider: Time duration between app process forked from Zygote and first initialization of content provider. Creating the app object and launching the main thread will be happening here. developers have little influence on the improvement here.
  2. Content Provider to App OnCreate(): Time duration between first initialization of the content provider to start of App.OnCreate(). it includes the whole time taken for Content providers in the app.
  3. App OnCreate() Start to App OnCreate() End : Time duration between start of App.OnCreate() to end of App.OnCreate(). it includes time taken for App.OnCreate()
  4. App OnCreate() Start to First Draw of the frame: Time duration between End of App.OnCreate() to first draw of the frame. it includes time taken for initial activity initialization, inflating the first layout, onMeasure() and onDraw() of for initial layout.
1*4uXdtsarKpvwhNj61qoG_A.png?q=20
how-okcredit-android-app-improved-cold-startup-by-70-e02bda4836a8
1*zXGSxbZF0J9G1GeBMfQE6A.png?q=20
how-okcredit-android-app-improved-cold-startup-by-70-e02bda4836a8

We use Android studio CPU profiling for identifying the methods which take to run a long duration during app startup. To begin recording CPU activity automatically during app startup please do the steps on this doc.

Performance bottlenecks, we found.

1. Dagger Lazy

Dagger Lazy is a great way to delay expensive object initialization. Until we need those objects, they are not going to get initialized and saving some precious time during App start.

1*eQJlpP_po3zC34TjyXhx_w.png?q=20
how-okcredit-android-app-improved-cold-startup-by-70-e02bda4836a8

In the above image, you can see the class IAwsServiceImp_Factory is taking a huge time for initialization. This class is being used for uploading a file that is unused during app startup. Initializing classes like this lazily helped us to improve the precious time on app startup.

2. Offload SDK initialization from on App.OnCreate() to background thread.

All the code inside App.OnCreate() is to be executed as part of the initialization process on the main thread. Lots of libraries and SDKs recommend their initializations to be made in the Application.onCreate(). This will eventually increase Application startup time. We offloaded some of the initialization from the main thread to a background thread.

override fun onCreate() {
super.onCreate() setupDependencyInjection()
observeProcessLifecycle() Executors.newSingleThreadExecutor().execute {
firebaseRemoteConfig.get().fetchAndActivate()
setupJobScheduler()
setupAppsFlyer()
setupAnalytics()
trackDeviceInfo()
}
}

We were using coroutine’s GlobalScope.launch earlier for offloading to a background thread. Later we changed to ExecutorService. ExecutorService is being preloaded by Zygote. Coroutines, which aren’t preloaded, have a high initialization cost. You can read this article for more information.

3. Refactored launcher screen layout to flat view hierarchy

We flatten the view hierarchy using the Constraint layout. This improves the layout-and-measure stage of initial frame rendering. We constantly keep measuring the onMeasure() and onDraw() duration of those layouts separately.

4. Remove Firebase trace during App startup

Firebase performance monitoring is a service that helps you to gain insight into the performance characteristics. It provides helpful functionality such as performance metrics for individual methods as well as multiple other performance metrics. Unfortunately, the Firebase Performance library also comes with some hidden costs. it initialises through a content provider which is taking a decent time during app startup. On top of that, we were using firebase custom trace on App.OnCreate() for measuring the performance on production. This also took decent time. So we have decided to remove firebase performance from the app and we would be using in-house instrumentation tools.

1*prfd_JqWcRoO7ZflHu0f_Q.png?q=20
how-okcredit-android-app-improved-cold-startup-by-70-e02bda4836a8

5. Removed Date time object from Launcher Screens

We use org.joda.time as a date and time library in the App. It’s a popular time library for Java. It turns out that creating just one org.joda.time.DateTime() object during your app’s startup causes a significant slowdown due to it internally using getResourceAsStream() to load timezone data, which is very slow. We avoided DateTime during app startup and we are in the process of migrating the date and time library to java.time.

6. Lazily initialize Content Providers

We have firebase, Work manager, Lifecycle, and one third-party service which is initializing through the content provider. We initialized the work manager lazily using their On-Demand Initialization. All other content providers need to be initialized before App.OnCreate(), hence we can’t initialize lazily.

Adding to here more, the Jetpack AndroidX App Startup library provides a way to lazily initialize the content provider. Another benefit that the jetpack Startup library gives is, instead of defining separate content providers for each component that needs to be initialized, it lets you define initializers that share a single content provider. This usually saves ~2ms per content provider. We haven’t gone for that since we have only 3 content providers, hence the impact is low.

7. Avoided I/O Operation & JSON deserialization on the main thread during app startup

We enabled StrictMode for catching all I/O operations on app start and fixed those. Some of them were happening on third-party services and we reported those.

Overall Results.

With high investments into credible analytics and being vigilant for identifying app startup issues, we were able to reduce the cold startup percentage from 4% to ~1.2%.

1*0K4zEMPg2j5i56_oXzN-FQ.png?q=20
how-okcredit-android-app-improved-cold-startup-by-70-e02bda4836a8
This is the last 3 months slow cold start sessions percentage in Okcredit from Google play console

I hope you find our experience useful in helping you to reduce cold app startup time. Today, at OkCredit we monitor several dashboards that provide us insights on the performance of the most critical parts of our application to ensure that the OkCredit application continues to be a delight to our users.

Useful Links

Are you interested?

If you are interested in building for 50M+ MSMEs in India, check out our opportunities.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK