作为世界上最大的社交网络,Facebook的Android客户端面临着各种各样的使用环境(地理环境、Android设备以及移动网络等环境的差异)。也正是这个原因,为了检测自家Android客户端在发展中国家的性能表现,Android的产品经理、工程师在2013年的时候去了一趟非洲。当时我看到这个新闻的时候觉得有点怪异,后来看到他们这篇博客才有点理解他们这样做的原因了。
这群Facebook的工程师来到非洲之后,并在当地使用Facebook的最新版本的Android客户端。测试的结果的确让他们印象深刻:
- 当地的网络环境十分糟糕,App经常中断网络连接。
- 当地人民使用的Android设备内存小,导致App加载缓慢,而且经常崩溃。
- 他们的月流量在40分钟之内就用完了。
经过这个让人印象深刻的测试的之后,Facebook的工程师们开始对他们的Android客户端进行了一系列的优化。
性能优化
这里主要是改进了App在低端机上的性能问题。
- 问题:单核的Android手机在启动Facebook的时候更慢,这是因为app在启动的时候并行初始化了多个模块。
解决方案:在单核手机上延缓这些初始化过程到启动之后,甚至只有在某个模块要被使用的时候才开始初始化这个模块。
- 问题:信息流在网络环境差时加载速度慢。
解决方案:尽早地从服务器抓取信息流数据,用更多的时间来建立连接,并下载信息流的内容。
最终的效果是App的启动时间减少了50%。
数据处理效率的优化
非洲的旅程让工程师们发现流量在发展中国家非常昂贵,而且作为Facebook重要体验一环的照片则是流量花费的大头,于是为了让人民在不担心流量的前提下安心享用Facebook,工程师们决定对App里面的照片动刀:
- 寻找现有图片格式的替换者。经过工程师们的调研,在众多的图片格式中,最后工程师选择了Google的WebP。原因很简单:压缩效率高,而且对Android的支持好(毕竟就是Google提出来的)。使用
WebP 之后,相对于JPG格式的图片,流量省了将近 25% 到 35 %;相对于 PNG
格式的图片,流量省了将近80%。最重要的是使用WebP之后图片质量还没改变。 - 按照设备处理图片的能力来加载图片。在之前,Facebook的App都是统一加载最大分辨率的图片,这样做是为了让用户可以自由的缩放图片。后来改进之后,app最先加载的图片大小适合显示这个图片窗口大小一样。如果需要缩略图,app就只加载缩略图大小的图片,用户需要更高分辨率的图片,app也能加载,而且之前的统一加载最大分辨率的图片了。
- 调整缓存和重用图片的策略
。工程师测试了不同的缓存策略,不同的缓存大小,最后综合出最优方案。
最后的效果也是讲流量花费减少了50%。
网络优化
- 由于许多地区的网络环境比较差,这让Facebook的App的体验也变得十分糟糕,于是工程师也对app的网络效率和可靠性进行了一番改进。
- 使用OkHttp。Facebook 很早就开始使用Square公司开发的 OkHttp(一个开源的网络协议栈)了,现在Google
官方也从Android 4.4开始使用 OkHttp作为HttpURLConnection的默认实现了。 OkHttp
支持在糟糕的网络环境下面更快的重试,并且还能利用 SPDY 协议进行快速的并发网络请求。
利用Okhttp调整图片的预先抓取算法,确保app中下载队列前面的图片被优先处理,防止队列阻塞时间过长。
经过优化后,图片加载慢或者加载 失败的反馈少了将近90%。
App文件大小优化
工程师在非洲的时候发现人们使用数量最多的手机磁盘空间很小,也就是说这给用户升级带来的障碍,进而可以推断这些人们因为手机的空间问题而一直使用旧版本的app,那么他们也就无法升级享受前面提到过的优化后的app体验。于是工程师开始致力于如何对app文件大小进行优化:
- 利用Google
Play提供的功能为不同的Android版本、不同的Android屏幕分辨率的手机提供不同的安装文件。这样就可以在不同的设备上面进行功能的取舍了。 - 当然在这个过程中需要监测工具和测试工具来保证优化app文件大小之后app功能的正常性。现在Facebook的工程师已经开发出一套可以计算每个特性对Facebook
Android App贡献了多大的空间。 经过优化之后的文件大小减少了将近65%。
反思
Facebook 工程师们的非洲之旅让他们更加理解了移动app性能、数据处理的有效性、网络的可靠性以及app的文件大小对发展中国家移动市场意味着什么。
工程师在这之后开始对每次app新添加的特性都会进行各方面的测试验证,而且Facebook还有一套工具可以直接获得用户对这些特性的反馈,而且工程师开始将这些实践延伸到 Messenger 和 Instagram 的Android App。
英文来源于 Facebook工程师博客。