By Anton Krasov | Sarvar Dhillon

It’s difficult to imagine modern android apps that don’t implement some external libraries or SDKs. After all, most apps have to leverage some combination of network image loading, crash tracking, advertisement, or analytics libraries and SDKs. It makes sense - developers shouldn’t have to reinvent the wheel (several wheels, actually) every time they want to create an application. However, it turns out that many libraries and SDKs cause major startup delays and other performance issues. These delays can be hard to track down because developers typically have little to no knowledge of the library or SDK’s implementation.

Common Performance Problems in Libraries and SDKs

There are a couple of common problems that we’re constantly telling developers to look out for. It turns out that some of these problems persist in libraries and SDKs, which means it’s all the more important to be vigilant when it comes to using and understanding third party code.

ClassLoader.getResourceAsStream is the most popular performance problem we see in libraries and SDKs. If a library or SDK is provided in JAR instead of AAR) format, ClassLoader.getResourceAsStream is the only way to load resources. Developers use JAR instead of AAR for a variety of reasons, the main one being that they want to distribute one package for both Java and Android. Hung methods in the main thread are another common problem found in libraries and SDKs. Libraries and SDKs often need to be initialized, so it is convenient for their developers to provide an initialization method that does a lot of the heavy lifting. For instance, an advertisement SDK may acquire the list of installed apps to avoid showing you an ad for an app you’ve already installed. An A/B testing SDK may load feature toggles from a remote server. If the developers are not careful and do this heavy work in the main thread, your app will suffer. Reflection is another common problem. Library and SDK developers often use reflection to make it easier for other developers to use their library or SDK. For instance, an app developer can create a REST client or a DAO object just by adding a few Java annotations. Unfortunately, when not used carefully, reflection can introduce huge overhead to any Android app.

Libraries and SDKs - Real-Word Examples With Top Apps

Performance problems are pervasive in libraries and SDKs. Here we describe the problems in the following 11 popular libraries and SDKs and the apps affected:

Tapjoy suffers from the ClassLoader.getResourceAsStream problem. Here’s an example (textPlus 5.9.9):

1729ms for call com.tapjoy.TapjoyConnect.requestTapjoyConnect

Other affected apps include Bible 5.11.3, Akinator FREE 4.04, AlarmMon 6.1.8, Yokee 2.0.205, Keek 5.0.6, SimSimi 6.6.1.3, InstaFisheye 2.6.8, Jaumo 3.5.3, My Diet Coach 4.2.8, Talking Angela 2.4, and ZombieBooth 4.32.

Startapp suffers from both hung methods in the main thread and ClassLoader.getResource problems. Here’s an example (Lovely Photo Frames 4.0.2):

698ms for call com.startapp.android.publish.StartAppAd.init

Other affected apps include Flash Alerts 2.2 and Voice Changer 29

Heyzap also struggles with properly managing the main thread. Here’s an example (from Mackolik 3.3.6) in which Heyzap makes 3 calls of packageManager.getInstalledPackages(), which takes ~236ms:

241ms for call com.heyzap.sdk.ads.HeyzapAds.start

Yume, like many of the SDKs already mentioned, perpetuates the ClassLoader.getResource problem. Here’s an example (Talking James Squirrel 3.26.0):

2152ms for call com.kauf.marketing.YuMe.init

Other affected apps include: Talking Babsy Baby: Baby Games 3.30.0

ClassLoader.getResource just wont stop cropping up. It shows up again in the Joda-Time library, as you can see here in this example (Yahoo Fantasy Sports 6.4.0):

2259ms for call org.joda.time.DateTimeZone static initializer

Other affected apps include: TuneIn Radio - Radio & Music 13.6.1, My Pregnancy Today Tracker 1.17.1, LiveScore 2.1.4, Vevo - Watch HD Music Videos 2.1.8, Muslim Pro: Prayer Times Quran 7.0.6, and Timehop 3.1.1

Ormlite, too, suffers from calls to ClassLoader.getResource. In this example (from Anghami 1.8.58), the call takes nearly an entire second:

830ms for call com.j256.ormlite.android.apptools.OpenHelperManager.getHelper

Other affected apps include: Booking.com Hotel Reservations 8.4.2, Nike+ Running 1.7.3, Run with Map My Run 3.10.0, OLX Brasil - Comprar e Vender 10.1.3.28, and Kaave 1.8.0

ActiveAndroid’s reflection usage is a concern, as it can cause some serious app slowdown, as seen here in Myntra 2.4.0:

1421ms for call com.activeandroid.ActiveAndroid.initialize

Other affected apps include: Scribd - A World of Books 3.11

Jersey’s use of reflection is also pretty detrimental to app performance. It slows down Photobucket 3.3.6 (and a slew of other apps) significantly:

660ms for call com.photobucket.api.client.jersey.UserClient constructor

Yet again, ClassLoader.getResource finds its way into another SDK. AWS Android’s use of ClassLoader.getResource is exceptionally slow here in Moovit 4.2.7.137:

2371ms for call com.amazonaws.auth.CognitoCachingCredentialsProvider static initializer

Unsurprisingly, SLF4J also suffers from ClassLoader.getResource:

678ms for call org.slf4j.LoggerFactory.getLogger

What’s wrong with Logback? You guessed it - ClassLoader.getResource. See how it affects Audible 1.9.0 here:

1561ms for call org.slf4j.LoggerFactory.getLogger

Other affected apps include: Wiper 2.5, Marco Polo: PTT Video Chat 1.2.19, and Talkatone: FREE Texts & Calls 4.3

Recommendation: Profile the libraries and SDKs you use to avoid surprises



