Classes: Performance and network segmentation on Android

Chris MarraDaniel WeaverAlexandru PetrescuTomás Kabbabe

Operating at a scale like Facebook's isn't easy. We have thousands of engineers working on hundreds of projects, moving as quickly as possible. With such a distributed engineering culture, not everyone can be an expert on every topic — nor should they be.

Over the past year, we've built Android frameworks to address that by abstracting away specific details like CPU, RAM, and network technology into broad segments both in analytics and code. This lets us leverage our existing expertise of the things that matter most for our product so that every engineer can do the right thing by default without needing to reason about the gritty details. Segmenting on the characteristics that matter most to us has been incredibly powerful in giving people a common language to use around the company.

Today we're happy to open-source two of those tools: Year Class and Connection Class, which help you smartly segment based on device and network performance in real time. You can use them to adjust feature performance at runtime, and to analyze how different interactions are network- or device-bound for performance.

Both tools are available on our GitHub page, and we'll be keeping the definitions up to date as time progresses and the market shifts. Check out facebook/device-year-class and facebook/network-connection-class, and give us your feedback!

Devices

About a year ago, we realized that hundreds of millions of people were accessing Facebook from Android phones, but we didn't actually know much about them. Some people consumed a lot, and some a little, but we weren't able to differentiate between demographics, phones, and networks. We had a hunch that the devices themselves were leading to the biggest swings in performance, but more than 10,000 models were in active use; we needed an easier way to segment people and analyze usage differences. Because we wanted to segment on something indicative of performance, we came up with a new concept called Year Class — essentially classifying phones by what year we would've considered their specs “high end.” Year Class was a simple mapping of RAM, CPU cores, and clock speed to a number, but it became an incredibly powerful tool for us to analyze patterns across the hundreds of millions of Android phones regularly accessing Facebook.

Now, with the Year Class library, you can figure out the year class for a particular device with one line of code:

int year = YearClass.get(getApplicationContext());
if (year >= 2013) {
    // Do advanced animation
} else if (year > 2010) {
    // Do simple animation
} else {
    // Phone too slow, don't do any animations
}

Despite the success of Year Class for analysis and feature customization, we noticed that metrics related to network transfer didn't have clear performance correlations. Much like phones, not all mobile networks are created equal. America's LTE networks would surely be different from Korea's, and even Wi-Fi around the world couldn't be considered predictably fast. We needed Connection Class.

Connections

Knowing that we wanted a way to equitably compare connection quality, we started by instrumenting bandwidth and latency around the world. We first modified Proxygen, our open source HTTP stack, to send round-trip times back in its HTTP headers to the client, and then we locally measured the transfer speeds of every response greater than 10 kb. Because bandwidth over a network radio is inherently noisy, we applied a low-pass filter to measurements and kept a running geometric mean in order to keep an accurate estimate throughout a session. In addition, we kept historical averages of country, carrier, and network technology so we could quickly adjust our estimate when the active network changed.

We found that the average speed for a given network technology, like HSPA, can vary by 5x between countries, and that the distribution of different technologies around the world varies significantly. In India, a country with limited broadband infrastructure, 2G remains in active use, while the U.S. and Mexico lean heavily on Wi-Fi connections.

We decided that bandwidth alone provided a good enough measure of quality for this project, and thus segmented it into four different buckets: 0 - 150, 150 - 550, 550 - 2000, and 2000+ kbps. Based on where someone's bandwidth measure is, we'll map them into one of the four Connection Classes — Poor, Moderate, Good, and Excellent. Each boundary is 3.6x the value of the previous one, which provides a margin to allow bandwidth to change during a session without constantly bouncing users between classes because of it.

To calculate a user's current Connection Class, you have to tell the library when you're starting a network request and when it's done. It will keep track of how many bytes were downloaded and how long it took. After enough samples have been gathered, it will broadcast an event with the user's current Connection Class.

// Implement
public interface ConnectionClassStateChangeListener {
  public void onBandwidthStateChange(ConnectionQuality bandwidthState);
}

// Initialize Connection Class
ConnectionClassManager ccManager = ConnectionClassManager.getInstance();
// Initialize Device Bandwidth Listener
DeviceBandwidthSampler sampler = DeviceBandwidthSampler.getInstance();
// Register Listener
ccManager.register(mListener);

// Later
sampler.startSampling();
// Download image or video
sampler.stopSampling();

We've been using Connection Class in our products and analytics for several months now. Along with Year Class, it provides helpful insights into how different usage behaviors on Facebook are driven by network performance, device performance, or both. It has helped us disable autoplay video on slow connections, automatically adjust image quality for your connection, tune our network parameters, adjust our image- and comment-fetching logic, and gain a better understanding of where to focus our efforts on improving network performance.

Check out the projects on GitHub and let us know what you think!

Keep Updated

Stay up-to-date via RSS with the latest open source project releases from Facebook, news from our Engineering teams, and upcoming events.

Subscribe
Facebook © 2017