第三方库和SDK中隐藏的性能问题

很难想象现在的 APP 不会使用任何第三方库或者 SDK,毕竟大部分 APP 都会需要进行网络图片加载、闪退追踪、广告或者用户行为分析。这是很有意义的,开发者不应该在每次开发 APP 时都重复造轮子。然而很多第三方库和 SDK 都会导致 APP 启动变慢以及一些其他的性能问题。而这些性能问题通常都很难追踪分析,因为大部分开发者都对第三方库和 SDK 的实现细节了解很少,甚至完全没有了解。

第三方库和 SDK 中常见的性能问题

我们一直在向开发者们强调第三方库和 SDK 中存在的几个常见问题,然而其中的一部分问题依然存在,因此,在使用第三方库和 SDK 时,对它们的性能问题保持警惕非常重要。

  1. ClassLoader.getResourceAsStream 是第三方库和 SDK 中最常见的性能问题了。如果一个库的文件格式是 JAR 而不是 AAR) 格式,那 ClassLoader.getResourceAsStream 就是读取资源文件的唯一途径了。开发者选择以 JAR 格式打包库文件有很多原因,通常是为了为 Java 和 Android 平台提供统一的库文件。

  2. 主线程内的“夯方法” 是另一个常见的性能问题。通常库都需要一个初始化的过程,所以会有一个初始化方法来进行初始化操作,这个过程可能会耗时较长。例如广告 SDK 可能需要获取已安装 APP 的列表,用来避免显示已安装 APP 的广告。A/B 测试的 SDK 可能需要从服务器获取开关参数。如果开发者在调用这些初始化方法时不小心使用了主线程,那 APP 的性能就会受到很大的影响。

  3. 反射 是又一个常见的问题。库的开发者常常利用反射使得库更容易被其他人使用。例如可能有的 APP 只需要加入几个注解就可以创建一个 REST 客户端或者 DAO 对象了。不幸的是,对反射的使用如果不小心,就很容易严重降低 APP 的性能

实际榜单 APP 所使用的第三方库和 SDK

第三方库和 SDK 中的性能问题非常普遍,下面是存在上述问题的 SDK 以及受其影响的 APP:

  1. Tapjoy
  2. Startapp
  3. Heyzap
  4. Yume
  5. Joda-Time
  6. OrmLite
  7. Activeandroid
  8. Jersey
  9. AWS Android SDK
  10. SLF4J
  11. Logback

Tapjoy  

Tapjoy 受到了 ClassLoader.getResourceAsStream 的影响。下面是一个例子(textPlus 5.9.9):

tapjoy
调用 com.tapjoy.TapjoyConnect.requestTapjoyConnect 耗时 1729ms

其他受到影响的 APP 包括: 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, 和 ZombieBooth 4.32.

Startapp  

Startapp 受到了主线程内“夯方法”以及 ClassLoader.getResource 的影响。下面是例子之一(Lovely Photo Frames 4.0.2):

Startapp
调用 com.startapp.android.publish.StartAppAd.init 耗时 698ms

其他受到影响的 APP 包括: Flash Alerts 2.2Voice Changer 29

Heyzap  

Heyzap 受到了主线程内“夯方法”的影响,下面是例子之一(Mackolik 3.3.6),其中调用了3次 packageManager.getInstalledPackages() 方法,耗时约236ms

Heyzap
调用 com.heyzap.sdk.ads.HeyzapAds.start 耗时 241ms

Yume  

Yume 和其他 SDK 一样,也使用了 ClassLoader.getResource 方法。以下是例子之一(Talking James Squirrel 3.26.0):

Yume
调用 com.kauf.marketing.YuMe.init 耗时 2152ms

其他受到影响的 APP 包括: Talking Babsy Baby: Baby Games 3.30.0

Joda-Time  

Joda-Time 同样存在 ClassLoader.getResource 调用问题,下面是例子之一(Yahoo Fantasy Sports 6.4.0):

Joda-Time
调用 org.joda.time.DateTimeZone 初始化函数耗时 2259ms

其他受到影响的 APP 包括: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, 和 Timehop 3.1.1

OrmLite  

Ormlite 同样存在 ClassLoader.getResource 调用问题,下面是例子之一(Anghami 1.8.58),耗时整整一秒:

ormlite
调用 com.j256.ormlite.android.apptools.OpenHelperManager.getHelper 耗时 830ms

其他受到影响的 APP 包括: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, 和 Kaave 1.8.0

Activeandroid  

ActiveAndroid 使用了反射,对 APP 性能产生了严重的影响,下面是例子之一(Myntra 2.4.0):

activeandroid
调用 com.activeandroid.ActiveAndroid.initialize 耗时 1421ms

其他受到影响的 APP 包括:Scribd - A World of Books 3.11

Jersey  

Jersey 对反射的使用也严重降低了 APP 的性能,例如 Photobucket 3.3.6:

com.photobucket.android Iricle Graph
调用 com.photobucket.api.client.jersey.UserClient 的构造函数耗时 660ms

AWS Android SDK  

AWS Android 也使用了 ClassLoader.getResource,严重降低了 APP 的性能,例如 Moovit 4.2.7.137:

AWS
调用 com.amazonaws.auth.CognitoCachingCredentialsProvider 的初始化函数耗时 2371ms

SLF4J  

意料之中的是 SLF4J 也使用了 ClassLoader.getResource:

slf4j
调用 org.slf4j.LoggerFactory.getLogger 耗时 678ms

Logback  

Logback 同样存在 ClassLoader.getResource 的问题,例如 Audible 1.9.0:

logback
调用 org.slf4j.LoggerFactory.getLogger 耗时 1561ms

其他受到影响的 APP 包括:Wiper 2.5, Marco Polo: PTT Video Chat 1.2.19, 和 Talkatone: FREE Texts & Calls 4.3

建议:使用第三方库和 SDK 之前务必测量其性能