
If You're Programming a Cell Phone Like a Server, You're Doing it Wrong - consciousness
http://highscalability.com/blog/2013/9/18/if-youre-programming-a-cell-phone-like-a-server-youre-doing.html#
======
canthonytucci
> Every decision you make should be based on minimizing the number of times
> the radio powers up.

This is lunacy. Ok, lunacy is a bit strong. But I disagree with this and am
throwing a "premature optimization" flag.

Modern phone batteries last plenty long, and the radio being on is nothing
compared to the big bright screen.

/edit Given the opportunity to chose, I know I would gladly sacrifice a few
minutes per charge battery life for a better user experience, especially since
my phone never gets below 20%.

Your users will be better served by you fixing bugs or adding features.
Really, unless you're a huge team with a huge budget, there's other stuff to
worry about in your app experience before "maximizing battery life" should be
a responsibility you want to help the OS/device maker with.(If you're one of
the lucky ones who has the time and money to do both, by all means, go nuts.)

Being conservative with resource usage is sound advice. Making battery usage
the prime concern for most apps is overkill.

Games and other applications that you know users will have open for extended
periods of time, and/or that are already eating up battery should give this
issue some thought, everyone else, really, don't worry about it.

~~~
kintamanimatt
Respecting known limitations and working within best practices is absolutely
not premature optimization. If you know that using the mobile radio in a
certain way is a source of excessive battery usage, it's silly to just
disregard this information. It's not premature optimization if you know where
the performance issues are from the outset, and these performance issues are
so incredibly common that the Android team put out videos about them.

The mobile radio will eat your battery very quickly, and probably chews
through as much power as your screen. If you want to see how expensive it
actually is, disable fast dormancy†. A slightly less brutal demonstration can
be had by opening an OpenVPN connection. The keep-alive packets will keep your
mobile radio in a higher power state, pretty much in the same way some
disrespectful apps do and you'll (quite unsurprisingly) see your battery drain
faster.

A badly written app can drain hours of battery charge, not minutes.

> Your users will be better served by you fixing bugs or adding features.

Excessive power drain is undoubtedly a bug. I absolutely love apps that
respect the fact I want to go as long as possible without charging my phone. I
might often be in a position where I can't charge my phone too. (Carrying a
second or third battery is useful, if you've got a phone that has a
replaceable battery.)

> Really, unless you're a huge team with a huge budget...

It's quite trivial to think about performance and battery life. This is
something every mobile developer should be thinking about from the get-go
anyway, and if you can't afford to write an app that performs well, you can't
afford to write an app.

> Making battery usage the prime concern for most apps is overkill.

I'll uninstall apps that I identify as too power hungry without a second
thought, and I'll also write negative reviews too. I'm pretty sure that when
put in this light, power consumption suddenly becomes important.

\--

† Don't do this. Some phone networks are misconfigured and may fail to ever
recognize that the phone is FD-capable again.

~~~
kevin_nisbet
I just want to add in from a network carrier perspective.

I work for a mobile operator, and have had to work on several network issues
related to poorly designed apps. I agree with kintamanimatt on this, it's not
premature optimization, you need to know the cost of what you're doing. There
is an incredible resource cost, to all the naive developers making apps these
days, that treat the wireless interface as an always on connection.

1\. Server polling every minute We actually sent one customer an invoice for
over $100,000 because they had a particularly bad application that polled a
server every minute. This was only an internal app used by a few hundred
people, but they used it at their office, and it caused constant blocking on
the cell site covering their office. This actually broke cellular coverage
near their office, and caused issues for all the other customers in the same
area. Ultimately, we said, we can help you fix you're app, you can pay the
invoice to upgrade cell coverage to you're office, or get off our network. In
this instance, we helped them fix their app, so it only interacted with the
server when something needed to be changed (the server pushed changes), which
was actually quite easy to do. This simply isn't the same thing, as writing an
inner loop in assembly, to shave off a few microseconds in runtime, which
would be premature optimization, and actually making robust software that
works well wherever it is used.

2\. Synchronized network access This one has been the bane of us on a few
occasions. If you write a network access to be like a cron entry, that run's
not only every 15 minutes, but does so at exactly the same time between all
devices. We get to hunt you down, and scream, as our wireless network
crumbles. When every device, wakes up at the same time, and asks for a higher
power state, at exactly the same time, the network will only process so many.
The funny thing is, you'll test this yourself and not see anything, but then
when you release your app, you might find 30% of those checks are failing for
some reason, and struggle to figure out why. For any one who is thinking, well
the operator should add more capacity, the answer is we do, but ultimately the
customer pays for the network build.

3\. High usage apps What happens is, your device vendor, is in the interest of
protecting it's customers as well. We once had an app on our network, that
would treat all reject codes, as a cause to retry. This caused it, to every
time it was run, begin uploading data, over and over again, leading to
thousands of dollars in bills to the customers for excessive data usage. The
device vendor, pulled the app from their stores.

Now, how do you feel, about having to plead the case why you should be allowed
to continue to sell your product, not only to the device vendor, but the
carrier who found the problem, prove that you fixed it, have our bureaucracy
test that you actually fixed it, and maybe if we feel like it, let you sell
again. It's not as simple as fix the bugs, you might actually lose you're
ability to make money of you're software, for months while this get's sorted
out.

What do you think you're store rating will be, when all your customers get
sent a $5000 bill for using your app?

Now the question is, should there be a better way, and I'd like to see more
from mobile vendors, in making it stupid easy to be smart about this. In the
phone API's, if I need to do a background update, I should be able to register
with the OS, and say, I have an update to do, within the next 15 minutes, let
me know when you have an active radio connection. You're phone goes into a
high powered radio connection, and bam, all you're background updates now go
out together. Need to send notifications, here is our push API, only interact
with the mobile when an update needs to be done. If the API's you're using,
are designed for mobile, and take alot of this network stuff that you
shouldn't need to know into account, it's a lot easier for the naive
developers to do better by blind luck.

\-- * my views in this post are my own, and do not reflect those of my
employer.

~~~
kintamanimatt
Thank you for this insider's insight. It's not something you come across every
day!

Aside from these things, is there anything else as a mobile developer that I
can do to make your lives happier? I'm not guilty of any of those things
you've mentioned and try to write well-behaving apps, but I'm always on the
look-out to find out about stuff I don't even know I don't know!

Also, perhaps you could you lobby your higher ups to put together some kind of
best practice guide from a network operator's perspective. I know the Android
team do touch on this in their guides and in the Google I/O conference talks,
but I'm guessing there's additional information that would be beneficial.

~~~
kevin_nisbet
kintamanimatt, there are definitely a few other things to look out for. One
thing to be careful of, is my perspective is based mostly on an escalation
standpoint, so I don't necessarily get a complete view of the ecosystem. Also,
without knowing what sort of apps you develop, it's hard to be too specific,
since some items are more relevant to void, than they are to web, etc.

1\. Power States On UMTS, if the radio is "idle", it won't lose packets, but
just a small amount of data, isn't enough to trigger a transition to a higher
power state. These packets generally won't be lost, but can take 2 seconds or
more to transit the RF network. If a transition is required, from the lowest
power state, that alone can take 500-800ms. The important lesson from this, is
that when just starting out a TCP/IP connection, it could be very slow for the
first little bit, until the phone/network realize there is more data passing.

On LTE, this is less of an issue, as there are only two power states, which
are idle and active. As such, you always have to transition to an active power
state to do any data, and the transitions have been significantly optimized.
However, the transition can still take a few hundred ms in this case.

This mostly becomes an issue, when you want to do something in real-time. We
see lots of reports and have many investigations on things like call setup
time on voip connections, etc. From an app perspective, this can be pretty
hard to account for, but with the move towards LTE, this will constantly get
better for you, since it's both faster and simpler.

2\. Packet Loss This point is hard to get across internally sometimes, but
packet loss will occur. It's a radio network, and there are interference
sources, and situations where we can't deliver every packet within a
guaranteed time. You'll also get temporary losses of connectivity (user goes
into a tunnel). This can get even weirder, where we get stuff like the uplink
is working, but the down-link has very high loss.

We have seen many DPI, IDS and Firewall vendors have problems with this packet
loss, and may cause inspection to fail, or the connection to get delayed. One
thing that often happens, is these vendors don't use a large enough reassembly
buffer for a mobile network. With the higher latencies we get on wireless
networks, there tends to be more in-flight data at any one time. On CDMA, when
a re-transmission was required, more than 100 packets of in flight data could
pass before the ack/sack indicated the packet was to be re-transmitted.

3\. Initial Window On the server side, it should be fine to set the initial
window to 10 packets as per the ietf draft: [http://tools.ietf.org/html/draft-
ietf-tcpm-initcwnd-00](http://tools.ietf.org/html/draft-ietf-tcpm-initcwnd-00)
I haven't had an opportunity to test this out, but my gut feeling is this
should actually help, as the more pending traffic will help indicate what's
happening from a power state standpoint. There are guides for many different
OS about how to change this setting, as it won't be applied by default.

4\. Exponential Back off This probably isn't so important at you're level, but
we've had issues more at a device stack level, that if some piece of the
network is lost, we get two problems. Fixing the piece of the network, and
fixing the "mass calling event", which is all the devices trying at the same
time to reconnect to that resource. This is mostly out of you're control, but
perhaps keep this in mind for your own server's benefit. If your server goes
down, don't have all you're clients go nuts trying to re-establish connections
as fast as they possible can.

5\. SMS Just in case you use SMS in any way, perhaps as part of push, one
property of SMS, is if it's not successfully delivered on the first try, when
it get's queued for redelivery, it could be delivered several hours later.
Also, at least on our network with the newest technology, we've had some bugs
we've had to look into with the same SMS being delivered multiple times. One
property of SMS you can also take advantage of, is if the device is out of
coverage (powered off, tunnel, etc), when it comes back into coverage, the
pending messages should be delivered.

6\. Reject Codes HTTP and many other services usually have the concept of
transient failure and permanent failures. Make sure not to retry on permanent
failures. I got at this in my previous topic, but we've seen more than once,
where something like a large email get's stuck in an outbox, because the mail
relay has a maximum size limit on it. However, the rejection occurs after the
upload, so the device sits their constantly uploading the same email over and
over again. I'd even be careful with transient failure, and if the transient
failure occurs for more than 3 or 4 tries, or an hour, to give up.

7\. Compression If you can, you may as well use compression to the best of
your ability, to keep resources smaller and faster. Even though the network is
faster, it'll still deliver a smaller payload faster than a bigger payload.

8\. Packet Size This one is often missed, but can be hugely important. And I
almost forgot to tell you. What happens in a mobile network, is you have IP
traffic that is destined towards the mobile. However, the mobiles position and
pathway isn't fixed, so our network has to track the user and update the path.
The way this is done, is network equipment will encapsulate the IP traffic
with additional IP headers, for delivery internally within our network.
However, our network has the same limitations for maximum packet size. So what
happens, is when we do our encapsulation, we have to chop the packet into
pieces, and then put it back together on the air interface. For awhile, we
also used to just IP fragment you're packet into smaller pieces, but
unfortunately this is also problematic as devices don't necessarily do the
best job joining the fragments either, especially if they get delivered out of
order.

So on my network, we use something call mss clamping, to limit the maximum
size of TCP payload data in a single frame. We do this, so that when we
encapsulate the packet, it will fit into one packet with our headers. However,
MSS is a negotiation that only happens on TCP, so it cannot happen on UDP
traffic. I also know for a fact, that not all carriers will do this, and I
have talked to one or two developers about why their app will work on our
network and not others. This is something you can adjust server side, to be
consistent across carriers. As such, on the public interface of the server, I
would recommend something like a MSS of 1350 bytes, which is enough for our
internal headers, and IPSEC, but not require the packet to be chopped, than
reassembled by the network.

As for lobbying the higher ups, I'll see what I can do. I think it's a great
idea, and carriers worldwide aren't doing enough in the space. However, this
is a really tough one, since as a large company, communications and branding
are greatly metered, and it doesn't help to do all this work, and have no one
read it anyway, because app stores today seem to be about volume, not quality.
Really, what I'm seeing on my side of the network (The Packet Core), is a lot
of the technology development, is to allow the network to be more flexible and
robust towards the way it is used, than attempting to control the ecosystem.
Ultimately what happens more and more, is we get just strait PC's connecting
to our network, and we want to offer a superior experience in this space.
Also, the most efficient devices are losing, where blackberry used to be an
order of magnitude more efficient than everybody else, has largely been eroded
by having a faster network and competing devices although less efficient,
deliver superior experience.

However, a little bit of searching did turn up some initiatives. Not so much
best practices, but in Canada the major carriers put together a consistent API
access for location, SMS, and billing.
[http://canada.oneapi.gsmworld.com/](http://canada.oneapi.gsmworld.com/)

Also, it looks like ATT has some information, but it looks like it's more
geared at enterprise, and most of the content is locked:
[http://developer.att.com/developer/forward.jsp?passedItemId=...](http://developer.att.com/developer/forward.jsp?passedItemId=200100)

Hopefully we will continue to see, more partnerships among carrier, more
standardization from the 3GPP and GSMA, and better API's to get the ecosystem
more mature, and it'll be better for everyone. I'm also hoping to see more
work on SCTP or multipath TCP, so we can start to see connection level
handoffs between different access technology, ie wifi offload when you're at
home. There are some technologies for call continuity today from you're wifi,
but they're amazingly complicated, and only work in very specific scenarios.

\-- * my views in this post are my own, and do not reflect those of my
employer.

~~~
kintamanimatt
Thank you! Seriously, this was very insightful and will be helpful! I hope
more app developers see this comment too.

------
DougWebb
The last thing I'd want is for my apps to each be downloading several MB of
data they think I might need in the next few minutes. I can easily control how
much battery life is remaining on my phone by plugging it in. I can't control
how much of my data plan an app is using, except by uninstalling the app.

Besides, in my experience the biggest drains on battery life aren't data
transfers, they're (a) having the screen on, especially when bright, and (b)
being slightly out of range of a cell tower, and constantly dropping and
reacquiring a 3G connection. The latter turns my phone into a hand-warmer and
chews up my power.

~~~
tjohns
Foreground prefetching aside, there are controls that let users disable
background data prefetching/syncing. In fact, it's even one of the buttons on
the standard "power control" widget.

While the screen is definitely a huge power drain, it's easily controlled by
the user. Poorly behaved apps will drain battery regardless of what the user
does, and definitely _can_ be a huge drain. These used to be a lot more common
when Android first came out -- many of these apps got better when users got
better visibility of battery usage and started complaining to app developers.

And in general, we're talking kilobytes of data here. Not megabytes.
Prefetching is good for metadata and text content; image content and other
large assets should be an opt-in feature. (Android's "News and Weather" app
was a good example of how to do this right.)

~~~
DougWebb
That control, like the permissions approval dialog, is a blunt tool. Sure, I
can turn background data completely off, or I can let my apps run wild with
it. There's no middle ground and no per-app control (unless the app developer
provides one.)

KB of data could be reasonable, depending on how often its being fetched. But
the OA specifically mentioned retrieving several MB of data for use "during
the next few minutes." If that's an app that doing some kind of news feed to
an always-running widget, and it's grabbing images and stories in case I might
want to read them, it can really add up.

------
doublerebel
Actual title _" If You're Programming A Cell Phone Like A Server You're Doing
It Wrong"_ is a much more accurate statement, and a different topic.

On topic, this is why I prefer native (or at least non-webview) apps. The
control over the connection and app lifecycle provides a better experience and
better analytics.

------
ultimoo
Great article, made me explicitly aware of something I had at the back of mind
as a web developer.

Another point that struck me is that when I briefly used Android more than a
year ago, there was a nifty tool that showed which app drained what %-age of
the battery. If I am having troubles with my battery life on Android, I am
likely to uninstall (or not use) an app that consumes more than its fair share
of the battery.

I haven't seen an equivalent statistics pane in iOS, I wonder whether Apple
will introduce it at some point to encourage app developers to author more
efficient apps.

~~~
gardarh
The problem with the battery statistics is that even though an app that is
causing battery drain it might not be registered with that app. Imagine an app
that sends a 1kb probe message every 15 seconds in the background thus keeping
the radio alive the entire time (i.e. never allowing it to idle). I believe
that the battery drain caused by the radio usage would count towards "Android
System" and not the app when in reality the app would be shortening your phone
battery lifetime significantly.

Assigning battery usage to apps is a hard thing as there are so many grey
areas. OTOH you will notice apps that are stuck in CPU expensive loops that
will not terminate, however this is not that common in my experience.

The Android battery statistics are nice but they usually don't provide me with
a useful answer to the question: Which app is really draining my battery.

------
csense
Since Android is an open system, would it be possible to write an app that
runs on a phone and forces applications to batch transfers?

I'm thinking of a "limiter" app that runs locally on the phone, and disables
TCP/IP transmissions every 18 minutes out of 20. That way things like email
you can still get relatively quickly, but the radio's only on 10% of the time.

Developers and users both being aware of the problem and trying to fix it
might mean their solutions collide. E.g. a badly behaved app that tries to
access the network once every 30 seconds will always get through during the
2-minute window, but a well-behaved app that only hits the internet every 10
minutes might miss the window entirely.

So maybe the limiter should intercept outgoing TCP/IP connections, lie to the
initiating app and tell it the connection happened but the remote end isn't
sending any data, then connect the outgoing app to the real remote end when
the radio switches on. Of course if there's an application-controlled timeout
interval on the connection, it'll trigger and the 10-minute-interval app would
miss the window.

You might get around that problem by using whatever UNIX signal Ctrl+Z
generates, to lock up an app entirely when it tries to open an outgoing
connection, then resume it when the radio's on. Of course, this'll probably
lock the app's UI too, so it'll become totally unusable. Although if the
limiter acts like a screensaver and goes away whenever the user's recently
given any touch or keyboard input, that doesn't really matter, does it?

Or maybe Google should make an API where an app can say, "I want to make a
connection, and I'm willing to wait if turning the radio on right now wouldn't
be good for the user."

~~~
mike_esspe
You can do similar to what you want right now: pass to AlarmManager flag
ELAPSED_REALTIME, and your event won't be delivered, until device is waked up.

------
jchrisa
Shameless plug for Couchbase Lite, our embedded database for iOS and Android,
with built-in sync. Let us optimize the network traffic so you can write
features.

Dev info: [http://mobile.couchbase.com](http://mobile.couchbase.com)

------
thibauts
The author talks about Google Cloud Messaging to avoid polling. I've been
researching the topic and gave it a try with websockets without much success.
TCP connections tend to hang on cell tower switching and I suspect TCP
keepalives keep turning the radio on.

I really wonder how to implement push to client on the html5 platform. I even
wonder if this is possible at all for now.

~~~
fulafel
cell tower switching is transparent to TCP except for delayed packets. TCP
keepalives are off by default and the default interval is 2 hours.

------
Zigurd
> _Every decision you make should be based on minimizing the number of times
> the radio powers up._

It doesn't have to be "every decision" if you architect the app to not do
CRUD-over-mobile-data and do sync instead.

This not only improves battery life, it has a strong positive effect on
perceived performance and interactivity.

Fortunately, there will soon be a book all about that (ISBN 1118183495).

------
joeframbach
The article is specific for native apps. Is there something I can do to bundle
requests together on browser-based sites? Does it matter there? I asked
stackoverflow but nothing came of it yet:
[http://stackoverflow.com/q/18909185/1253312](http://stackoverflow.com/q/18909185/1253312)

------
kevinbowman
Given the "preload any data the user might need in the next 2-5 mins"
statement, how do people suggest we handle live streaming of updates (eg
commentary on a sports event)? Presumably websockets are ok as it's more of a
"push" model for the network than a "poll" model?

~~~
jaytaylor
> Presumably websockets are ok as it's more of a "push" model for the network
> than a "poll" model?

This is seems incorrect - as I understand it, a websocket holds open a TCP
connection indefinitely, which would require the radio to stay in its active
state as long as the websocket remained open.

See also: [http://stackoverflow.com/questions/4456407/iphone-keep-
webso...](http://stackoverflow.com/questions/4456407/iphone-keep-websocket-
open-in-background)

~~~
ryanpetrich
I can't speak for websockets, but holding a TCP connection open indefinitely
does not require that the radio stay in its active state. On iOS, setting the
kCFStreamNetworkServiceTypeVoIP property on the connection allows the radio to
return to the idle state and reawake when it receives data on the socket.
Android may have similar APIs.

~~~
sliverstorm
Wouldn't the radio have to wake on a timer to scan? How else will you notice
there is data waiting on the other side of the connection?

~~~
ryanpetrich
The radio is in a low power idle state, the same state used to wait for
incoming phone calls and text messages.

------
minimax
How does the power usage of the wifi radio compare to the cell radio? Does it
use more or less power?

~~~
kintamanimatt
Vastly less. I can save a few percent of battery life an hour just by using
wifi instead of the mobile radio for data.

------
zmmmmm
So what happens in a situation like long polling?

Suppose no data is being transferred for 60 seconds ... is the radio kept on
at maximum power? Or does it power down in between? Or does it turn off and
break the poll (abort the TCP connection)?

------
lucb1e
Oh, shit.

    
    
        apt-get remove apache2 php5 ...
    

And here I thought running Debian (for ARM cpus) on your phone was cool.
Apparently I'm Doing it Wrong.

Puns aside, good article. If everyone did this (for example caching for 2-5
minutes ahead) things would run a lot better! Next time I'm going to code an
app, I'll read through everything on this page first.

------
AsymetricCom
Just another bugle call for developers and users to forfeit more of their
rights to our mighty big data and cloud land owners. Is your app ready for the
"Internet of Things"?

~~~
kintamanimatt
A few months ago I'd have been happily hitting the downvote button along with
everyone else, mumbling to myself about how crazy you sound. Today, however, I
wish you weren't being downvoted because you're half way to being right.

I strongly doubt the intent of things like Google Cloud Messaging is to
intercept all your data and siphon it off to the NSA, GHCQ, and others. GCM is
an incredibly useful service that has been designed to make it easier to write
apps that use less power by eliminating polling. When you don't have to poll
you can keep the mobile radio in a low power state. But the trouble is, you
are indeed passing data (possibly even sensitive data!) through Google data
centers when you're using GCM and it's equivalents.

The tech industry seems to trust Google less today than it did this time last
year in light of the Snowden leaks, and quite rightly so.

~~~
AsymetricCom
I'm not even considering that perspective. I'm just wary of the neofuedalist
movement of technology in the last ten years or so, fueled by the mobile
platforms being subject to regulatory capture.

The fact that data being captured by intelligence communities already shows
you who owns this "land" and considers the "natural resources" theirs for the
pillaging, this is a great example of the kind of neofeudalism this proposed
platform is building. We just rent the internet, the data that it generates is
for the kings and gods.

The fact that these so called mobile platforms leave so much complexity to be
managed by the developer just goes to show that these so called platforms are
simply land grabs and don't actually offer anything to the developer except
his software locked down to a single platform. They don't need to offer any
service, just a rent collecting system for their captured land.

------
jheriko
of course, if you program for anything like you do for "real man hardware" \-
by which i mean targetting hardware and not a software platform e.g. a games
console or a proper native app, part of the 'web stack' etc.... you never have
a problem like this. :P

eventually you realise that C isn't fast enough and you can make it faster,
but nobody else cares because they spunk clock cycles and bytes everywhere
like they have billions of them (which of course they do... :D)

...and suddenly every language and platform is solving problems you never had
because you just weren't a bad programmer to start with, and instead of
solving your problems they are just tying your hands to prevent other people
from shooting themselves in the feet.

