Android - Performance Patterns
We live in data hungry times.
Users want more data, more often, and are spending more time searching for it.
As a developer of the next great social application,
this might seem a perfect match for your business plan.
But unless you construct your networking requests the right way,
your business plan might be a huge flop.
My name is Colt McAnlis.
And unknown to most developers, each individual networking request
can have a load of performance problems for their users.
At its core, networking performance is about reducing the amount of time
between when the user wants data and the networking returns it.
And there's a ton of things that influence that variable,
for example, bandwidth latency, cellular connection speed,
small mammals, apparently.
These are the typical things that users know about, and generally understand,
when it comes to networking.
But there's also a second set of performance concerns
that developers have to be aware of, which are a little bit more pragmatic.
For example, using the cell radio for networking is the number one killer
of battery performance for mobile devices.
And the more data you're transferring results in costs and charges for users.
See, most of the time, folks on limited bandwidth devices
don't appreciate you bringing down 2 gigabytes of image data
for your social media app.
In the end, it all boils down to two key things that developers need to focus on.
Number one, reducing the amount of time you keep the radio active.
And number two, reducing the size of the data that you're fetching.
Now, lowering the request count is actually a complex equation.
But for the sake of sanity, you can generalize it into three primary buckets.
Firstly is the stuff the user asks to do. So, like, update now.
Secondly is the stuff that the server needs to update you about,
like a returning response or letting you know that
there's new social data available.
And thirdly is the stuff that needs to be uploaded frequently,
like uploading analytics, or checking device location,
or something else that's interesting.
Now, the second two categories are really the prime candidates for optimization.
For example, you should never, ever, ever, poll the server regularly for updates.
You're basically just wasting bandwidth and battery
for the server to tell you that nothing's changed.
Instead, it's a better idea to leverage other services
like Google Cloud Messaging, which will let the server signal the app
when there's new content.
This will reduce the amount of battery the phone uses as well as reduce
the overall number of server responses that you need to worry about.
And for those situations where cloud push can't be used,
it's critically important to reduce the frequency
that those requests are made.
For example, rather than polling the server every five seconds
asking for data, try to use a backoff pattern
to reduce the number of requests and get mostly the same results.
And rather than letting your requests be strung out over time,
try to batch them together, so they happen in short bursts
to optimize for an active cell radio, which, will reduce battery waste.
And even try to think about prefetching your data
so that you can reduce the need for executing future requests
when you can do them now.
Now, stringing all of these optimizations together is a sure fire way
to reduce the number of overall requests, which will do wonders for battery life
and costs for your users.
And the good news is that you can update your app to adopt these patterns
without having to write a massive amount of code.
GCMNetworkManager is a Google Play Services API,
which helps to schedule network-oriented tasks
and handle batching for you.
This greatly simplifies the implementation of common patterns,
such as waiting for network connectivity, network retries, and exponential backoff,
basically all the good stuff you need with a single, helpful API.
Now, of course, the second large perf target is reducing the size
of the data in your request, which, as far problems go,
is kind of a personal favorite of mine.
Let's see if we can get all of this on one slide, shall we?
Firstly, watch the CompressorHead series of videos so that you understand
more about data compression in general and the algorithms that make up the science.
Then make sure you take the time to read my article on image compression
and go through and be hyperaggressive about the quality and format
of the images you're sending from the servers.
Remember, smaller is always better.
Oh, and if you're a game developer, then check out the "Texture Wranglin" talk
or the Crabby image format to get some better results for ideal textures.
And once that's done, go back and check out my "GZip is NOT enough" talk
to get a better understanding of lossless compression for text-based data.
There's an article on that, too.
Followed, of course, by a hard, clear look on how often you're sending around
XML and JSON packets, which hopefully will depress you,
and you'll realize that you shouldn't be sending around raw text data,
and instead, should be leveraging Protobufs or FlatBuffers formats,
which I've got a video on that, too. I talk a lot about compression.
Anyhow, if you're ever wondering how your app is using or abusing the network,
make sure to spend a lot of time getting familiar
with the networking tool inside of Android Studio.
It'll show you how often you make requests, their size,
and how long it took to complete the round-trip.
If something's going wrong, this tool is a first step in tracking it down.
But as we all know, this is just the beginning.
For a deeper discussion on any of the topics
I just rambled on about, check out the rest
of the Android Performance Patterns content.
And don't forget that there's a whole horde of developers out there
solving the same perf problems as you.
So stop by the Google+ community and ask for advice when you get stuck.
Anyhow, keep calm, profile your code,
and always remember, perf matters.
(music playing)