How Facebook Sped Up Photo Loading in iOS App, News Feed for Android


Facebook adopted a technique known as progressive JPEG to speed up photo loading in its iOS app, describing the process in a post on its engineering blog as an image format that stores multiple, individual “scans” of a photo, each with an increasing level of detail.

As for News Feed in its Android app, another engineering blog post details how the social network handles the extremely complex ListView behind the process.

Highlights of the post on PJPEG follow:

Our team took a look at how we can make photos faster on iOS and we found a way to reduce the data used by Facebook for iOS by about 10 percent and show a good image 15 percent faster than before.

Progressive JPEG (PJPEG) is an image format that stores multiple, individual “scans” of a photo, each with an increasing level of detail. When put together, the scans create a full-quality image. The first scan gives a very low-quality representation of the image, and each following scan further increases the level of detail and quality. When images are downloaded using PJPEG, we can render the image as soon as we have the first scan. As later scans come through, we update the image and re-render it at higher and higher quality.

Rendering images progressively in the Facebook app has some advantages:

  • Data consumption: PJPEG allows us to skip downloading smaller versions of an image.
  • Network connections: Since we don’t download smaller versions of an image anymore, we now use only one connection per image instead of many.
  • Disk storage: Storing fewer photos on disk decreases the amount of disk space used by the app.
  • One URL: Since we no longer need to download multiple images at different sizes, we can simply use one URL.

There is a downside to PJPEG: Decoding and rendering the image multiple times at varying scan levels uses more CPU (central processing unit). Decoding images can be moved to background threads, but the process is still heavy on CPU. The real challenge for us was to find the right balance between data usage, network latency and CPU utilization. For instance, we considered using WebP, since it is more optimal in file size than JPEG in some cases, but the format does not support progressive rendering.

We render three different scans of each photo:

  • First we render a preview scan: This is pixelated.
  • Then we render a scan that looks good to the naked eye. In fact, it looks almost perfect to the naked eye.
  • Finally we render at full-quality: the best resolution possible.

The result is that people see a good photo sooner!

And here are highlights of the post on rendering the News Feed in Android:

If you work on an Android app (or any touch-screen-based app, actually), there’s a very good chance you have at least one activity based on a ListView. In many cases, it may be the screen of your app where users interact with the app the most. In the case of Facebook for Android, this ListView is your News Feed. Keeping News Feed working well in Facebook’s Android app presents a variety of engineering challenges, starting with performance considerations for touchscreens.

Facebook’s News Feed, a popular screen in the Facebook for Android app, is an extreme example of a complicated ListView. This makes delivering a smooth scrolling experience especially hard.

First, each story you see in the feed is pretty tall, and contains several pieces of text and photos. This makes the challenge of binding all of the story’s data without skipping frames significantly harder.

Secondly, there are multiple variations of stories in your feed. Aside from a simple story containing some text and a photo, you can see multiple variations of attachments: a preview for a link, an album, a video, etc. The story might be shared, in which case the story contains another story inside it. Hardest of all, we need to render aggregated stories, which means one story can actually be composed of several stories that are related. A good example of this is when many of your friends wish you a happy birthday. These aggregated stories are the most challenging to render, as one of them can easily be twice as tall as the screen of the device.

As an extra challenge, the typical Android phone is not a high-end device. So the amount of computations you can fit in under 16.7 milliseconds is likely less than the amount on the majority of phones you develop on.

About a year ago, we felt it was the time to invest in a new architecture for our rendering code for News Feed. We knew we wanted to avoid the pitfalls of the previous design and try to get rid of our more fragile code. For that purpose we considered a new idea: Splitting each story in the News Feed to several items in the ListView. Using this idea, the header part of a story will be its own item in the ListView. This nice trick results in various advantages right away. First, this makes Android’s recycling effective again. If before, two custom views for a story were too different to have one recycled into the other, now, recycling is happening on a sub-story level.

The other idea we incorporated to the design is decoupling the binding logic from the custom views themselves. For this purpose, we basically split our previous custom view into two classes: a simpler “dumb” custom view, and a Binder class.

This rewrite effort has resulted in many benefits:

Readers: Have you noticed any performance differences in your Facebook iOS or Android apps?

Speed image courtesy of Shutterstock.

Some of the links in the post above are “affiliate links.” This means if you click on the link and purchase the item, we will receive an affiliate commission. Regardless, we only recommend products or services we believe will add value to our readers.

Leave a Reply

Your email address will not be published. Required fields are marked *

CommentLuv badge

This site uses Akismet to reduce spam. Learn how your comment data is processed.