Over the last year, we’ve been retooling our mobile apps to make them faster, more reliable, and easier to use. Several months ago, we embarked on a major step change for iOS and shipped a native re-write of Facebook for iOS. With Android, we’ve moved to a fixed-date release cycle and have been steadily making improvements over time so that Facebook performs consistently across multiple platforms.
Today, we’re releasing a new version of Facebook for Android that’s been rebuilt in native code to improve speed and performance. To support the unique complexity of Facebook stories across devices, we’re moving from a hybrid native/webview to pure native code, allowing us to optimize the Facebook experience for faster loading, new user interfaces, disk cache, and so on.
We rebuilt several of Facebook for Android’s core features in native code, including news feed and Timeline, to create a faster experience whether you’re opening the app, looking at photos, or interacting with friends. Now, you can comment and like a story more quickly, and photo loading is optimized to be much faster. We also built a new, automatically updated story banner to bubble up the newest stories, no matter where you are in news feed.
We found that we had to develop new solutions and abstractions in order to address several performance challenges along the way.
Performance Challenges
a) Reducing Garbage Collection: Memory efficiency has a dramatic effect on UI smoothness. Inefficient memory usage will result in many garbage collection (GC) events, which in turn can pause the application for multiple frames and cause a visible stutter during scrolling. We focused specifically on minimizing, eliminating, or deferring allocations in performance-critical code. We also deferred performing allocation-heavy code (like feed story parsing) until scrolling stopped and moved them off the UI thread.
b) Writing a Custom Event Bus: An event bus allows for a publish/subscribe flow, which allows communication between classes that should not be aware of, or dependent on, each other’s existence. Common event bus implementations use object iterators and reflection, which cause long operations and a lot of memory allocations. To solve this, we implemented a light-weight event bus that avoids all reflection and object iterators so it can be registered and unregistered during performance-critical areas of code like scrolling.
c) Moving Photos to the Native Heap: Loading photos is memory-intensive, and efficiently loading and handling bitmaps can be challenging. The standard method of allocating them directly on the Java heap can result in significant GCs and out-of-memory errors. We moved our bitmaps to be loaded on the native heap using the inPurgeable flag in the BitmapFactory class. This allowed photos to be allocated in native memory instead of the Java heap (Honeycomb and up) or in external memory tracked by the VM (Froyo/Gingerbread), which in turn significantly reduced their impact on our allocations and thus performance.
d) Writing a Custom ListView Recycler: View recycling speeds up scrolling performance. The stock Android ListView has view recycling support, but it is not efficient for list elements of very different row heights, such as in news feed stories. We wrote a custom view recycler, which detached heavy content views once they were added to the recycling heap. We also recycled substories in more complicated aggregated feed stories.
Looking Ahead
This new release creates a solid foundation for the Facebook for Android app moving forward. The infrastructure in place will let us continue to make the app even faster, smoother, and feature-rich. We hope you enjoy the new Facebook for Android app and use it to celebrate memorable moments, share your stories, and enjoy the holidays with your family and friends.
Frank Qixing Du is an engineer on the Facebook for Android team.