Wednesday, June 09, 2010

iOS Multitasking

By now you’ve seen the ads. Anyone who works in mobile totally saw it coming. It’s the supposed revolutionary way to do multitasking in iOS, the new name for the iPhone OS. It’s complete bullshit, and here’s why.

It’s Not Revolutionary
Personally, I don’t really care about this point. However, it must be noted that the multitasking on the iPhone is strictly speaking a proper subset of the multitasking architecture used by Android and Palm’s webOS. Does it really matter? No, not really, but it is certainly annoying to hear Apple talk about how they didn’t do multitasking in the past because they hadn’t figured it out yet. The notion that what they ‘came up with’ is some brilliant solution that it took four years to figure out is insulting to the intelligence of developers. Not that that matters...

It’s Not Multitasking
Even Apple is pretty honest about this ... to developers. For us they say “it’s actually something We call Fast App Switching, and it’s all most of you people need.” This is the feature that was done by Android and webOS for the last couple of years. On iOS, when a user switches apps or hits the home button, your app has a brief time when it “runs in the background.” Then it becomes suspended. In its suspended state, it is still in memory, but gets no CPU cycles. If the user re-opens it or switches back to it, then it picks up right where it was before. Assuming that it is like Android (and everything else about Fast App Switching is very similar), then as a developer you might need to save some transient data, like if there is a form that is half-filled by the user. However, often you will not need to do anything to take advantage of this, just recompile with iOS 4.0 as your target.
But wait, there’s more. You should not count on your app staying suspended indefinitely. In fact, there’s a very good chance it will be terminated (that’s the official word.) This is exactly what happens when you go to the home screen on previous versions of iPhone OS, your app no longer takes up any memory. Now the user can still ‘switch’ back to your app (or re-open of course), but now it will be a re-launch of the app. In other words, it is just like closing your app, then re-opening it on iPhone OS 3.x.
This can obviously lead to inconsistent app behavior. Sometimes the user might switch away from your app, then switch back and be back at the same screen in your app that they were at before. Other times, they could do the same thing, but instead they are back to the opening sequence of your app. Apple wants you to change your app to remove this potential inconsistency. They’ve kind of given you a way to do this. First, when your app goes from being active to suspended, a new event is fired to your application’s delegate. All you have to do is add this new method (applicationDidEnterBackground:) to your delegate. In that method, you can save the state of your application. However, you might not have enough time. You can wrap your code with a start/end task completion calls, and then get up to ten minutes to finish saving your state. Alternatively, you can incrementally save state. Now truth be told, many apps (especially games) already do this, so that when you restart your app, it always picks up right where the user left off. Apple has essentially taken this pattern that other apps have adopted, promoted it to a best practice, and give you some extra tools to make it a little easier to implement.
There is one other thing that you might want to do right before your app gets suspended. You can decrease the probability of your app getting terminated by freeing up as much memory as you can. The iOS Terminator is going to kill apps that use more memory first. So free up as much memory as possible, and maybe it won’t kill your app. There’s no guarantees though. If the user launches an app that needs a lot of memory (and don’t they all?) then it doesn’t matter how little memory your app takes up. Everything is getting terminated. Hence Apple’s desire for you to always save state and never rely on being suspended when the user switches back to your app. However, if you do that, then is there any point to freeing up memory? Well theoretically it should be quicker to switch to a suspended app than a terminated one, so by freeing up memory you will be increasing the probability that your users will get a slightly better experience.

What is Real Multitasking?
Well strictly speaking, true multitasking would be to allow any given application to continue running as  normal when it is no longer in the foreground. This is what happens on desktop computers, and that sort of sets the expectation for smartphones. I think this is actually how Blackberry works (or it used, it has been many years since I bought a new Blackberry.) It’s not how Android works, and it’s obviously not how iOS 4 works. The major problem with this on more limited devices is that it causes those devices to run out of memory and use virtual memory. This makes everything on the device run sluggishly, as everything becomes gated by the swapping between real and virtual memory. Those non-foreground apps can also consume CPU and network. The CPU consumption might be an issue if you tried to run multiple games simultaneously -- just like it would on your desktop computer. Apple claims the CPU/network access real kill your battery. We’ll examine that later. Regardless, once you decide that a background app can lose its right to memory, it can’t function anyways. CPU/network becomes a moot point. Both Android and iOS terminate background apps to free up memory, something no desktop OS will do.
So iOS and Android both use similar pseudo-multitasking to make it seem like multitasking to the user. To prevent memory from running out and hosing the system, they terminate background apps at will. Both operating systems give you a way around this, a way for you to continue to execute a program in the background. That is where the similarities end.
On Android, you can create your own background service. That service can be in its own process, i.e. it gets its own block of memory allocated to it. That way if your application gets terminated, the service lives on. However, a service can be terminated just like an app. So you cannot rely on the service always running, instead the service should be there to enhance your application. Further, Android gives you ways to get your service restarted/pinged on a regular basis to do work.
On iOS, there are just a couple of types of applications that are allowed to run as a background service. Even then, they do not get their own memory. Instead they stay suspended and the OS sends them events periodically that allows them to run in the background again while they do something. Apple says they do not want to provide the Android style background services, because they (Apple) decided that the great majority of apps would not benefit from this anyways. Further, they think that such an architecture would lead to many background services running, killing the device’s battery. So instead they picked the types of apps that they say will benefit from background processing: music players, navigation, and voice-over-IP. The most ironic part of this is that the enabled a class of app, navigation, that has the most harmful effects to your battery (well maybe games are worse.)
I’ll talk about battery life in a second. First I want to address this notion that Apple has determined which apps would benefit from background processing, and which would not. As both a developer and a user, this is offensive. Apple has little knowledge of how my app works, or of how my users interact with the app. Further, they are obviously wrong. I can give you three examples of apps that use background services on Android to greatly enhance user experience: eBay, Facebook, and Twitter. You’re probably not surprised that I cited my company’s app, but maybe the other two did surprise you. All three use a background service to periodically download time sensitive data (current price of items, friend requests, status updates, tweets, etc.) So when you launch the apps or switch to them, you do not wait for all of this data to be downloaded -- like you do on all three companies’ apps on the iPhone. Instead you are presented with some fresh data (maybe a few minutes old), while the absolute freshest data is being downloaded in the background. You get to immediately interact with the apps. On iOS it might be possible to allow immediate interaction, but the data can only be as fresh as the last time you ran the app. This will usually be hours old, which makes it virtually useless for these apps.
There is no question in my mind that user experience can be better on Android than on iOS for these apps, and I don’t think they are unique. I mean c’mon, we’re talking about eBay, Facebook, and Twitter. Perhaps you’ve heard of these companies? It seems obvious that any kind of real-time/interactive/social based website is going to benefit from background processing for their apps. That’s a pretty broad class of apps, but I doubt it’s exhaustive. I’m not smart enough to figure out all of the apps that would benefit from background processing -- and neither is Apple.

Battery Life FUD
Ok, but what about the last plank in Apple’s argument: battery life. Well, as I pointed out earlier, they enabled a class of application that is devastating on battery life: navigation. These apps require constant high precision GPS information, which is very expensive. So their argument is not consistent with their behavior, still that doesn’t make their argument wrong.
The apps that I mentioned earlier all are guilty of something that is supposedly deadly to battery life: they periodically use the network to download data. How bad is this? Well obviously it depends on how often, and how many network calls are made, along with how much data is being sent back and forth. I’ve done some experimenting on this -- hey I work on one of the apps on that list of naughty apps. In my experiment I had an app that downloaded 100K+ data every two minutes. The effect on battery life was less than 3%. That’s right. You could let such an app run in the background for days and days, and your phone would still have plenty of battery.
Now wait a minute, I know what you’re thinking. You can’t even go one day without recharging your phone, and you’ve got an iPhone that doesn’t have anything running in the background (by the way this is not true, Apple’s apps have been able to run in the background since the very first iPhone.) Further, you don’t even use it to make phone calls, yet it’s got maybe 12 hours of battery life. What gives? The answer is surprisingly simple, the screen. The screen on your beautiful phone is what drains your battery the most. So anything that involves the screen being on -- which is every kind of app on the iPhone currently -- will significantly drain your battery. Everything else they do has little noticeable effect on battery life, with two exceptions. Anything that rapidly changes that pretty screen will consume your battery even faster. That’s why many games will hammer your battery. I’ve had times where I played Civ on my iPhone for maybe twenty minutes, and it lopped off a third of my battery. That game doesn’t even have that much eye candy. The other battery blaster is the aforementioned GPS, for obvious reasons. All of those Android users with eBay, Facebook, and Twitter installed are doing just fine.

But You're Gonna Love It!
So with all of that being said... users will really appreciate Fast App Switching in iOS 4. Why am I sure of this? Because Android users have always loved it. It’s one of those things where iPhone users don’t know what they are missing. Thus it will be delightful for them, and they will think Apple is full of geniuses. Actually I think it will put some serious pressure on Apple to update the iPad to iOS 4 (or maybe 4.1? Will we ever run the exact same OS on the iPhone and iPad?) People will get used to having Fast App Switching on their iPhone, and they will be so annoyed that they don’t have it on their iPad. I hope we’ll eventually see the same thing with regards to general purpose background processing. Maybe one day this will be part of iOS, and then it will be annoying to use older versions on the OS that don’t have this feature.

Update: You can add Instapaper to the list of apps whose developer would like it to be able to run in the background, so that it can improve user experience. Marco has an interesting proposal to tweak iOS to suit the needs of his app, and no doubt many others. It's better than the current situation, but I still think it's foolish to try to figure out all of the types of apps that need background processing, and add special APIs for each such app. While at WWDC, I talked to developers who work on some very popular sports and weather apps, and they too were incredibly disappointed by iOS. One of them proposed a new type of remote push notification that would not be displayed and only processed in the background.

10 comments:

Jeremy Norris said...

Thanks for this writeup, it's very useful.

You cited examples applications that could well use a background service to download time sensitive data; eBay, Facebook, and Twitter.

Are local notifications powerful enough for this task? Can you define your own local event producers that get run periodically? When this was first announced, there was some indication that this was going to be possible. I can't find technical details for this feature. This is critical. If they aren't up for these kinds of tasks, then I agree with you - the "multitasking" support of iOS is very limited.

Michael Galpin said...

Thanks Jeremy. Your question is a good one. Yesterday at WWDC, I attended two sessions on multitasking, and compiled a large list of questions (Apple does not allow questions during their technical sessions, at least none of the ones that I've attended.) Apple had a lab on multitasking in the evening, where you could bring code/questions and get one-on-one attention from Apple's engineers. I went to it and spent an hour talking to an Apple engineer, going over my list of questions. Your question was on my list.

The answer is no. Local notifications are just like their remote brethren, except that the creator of the local notification has a handle on it that could be used to cancel the notification. When a notification arrives (local or remote) there are two possibilities. If your application is active in the foreground, or active in the background, then there is an event that will be fired to your application's delegate. It's up to the application on what to do here. This is just like on OS 3, except that "active in background" did not exist is OS 3. If your app is suspended or not running, then the notification is displayed to the user immediately. Your application knows nothing about it. If the user chooses to "open" the notification, then your application is switched to (if it is suspended) or is launched (if it is not running) and the notification data is passed to it.

alexganose said...

Love your writing! Article is great very useful. I still don't understand why apple didn't switch to an OLED if the screen is the main cause of battery depletion.

Anonymous said...

you say
"When a user switches apps [on android], or hits the home button, your app has a brief time when it “runs in the background.” Then it becomes suspended. "

I do not think this statement is accurate

http://blog.rlove.org/2010/04/iphone-os-4-and-multitasking.html

"Android does not kill applications on task switch"
and
"We allow apps to *actually* multitask until the system experiences memory pressure, at which point our OOM killer is able to kill applications in least-recently-used order"

Michael Galpin said...

@alexganose Thanks! I was discussing the OLED issue with my friend Terry on Monday. He blogged about it here: http://terrychay.com/article/retinal-burn.shtml (towards the end.) In my experience, the Nexus One gets better battery life than the Motorola Droid, and I've always thought it was because of the OLED. However, I do think a lot of users prefer the Droid's LCD because it is brighter.

@Anonymous My sentence was about iOS, not Android, so your edit to my sentence is inappropriate. However, you are correct about how Android works. I didn't make the distinction because the difference is insignificant. For a programmer, you must expect that once your app is out of the foreground, it is going to be killed. You must expect that it will be purged from memory, and when that happens, it no longer gets any CPU cycles, etc. Now whether that purging happens 1 second, 5 seconds, or 10 seconds after the app goes to the background, rarely makes any difference to the programmer. Now for the user, maybe the Android way has a slightly better user experience, it's hard to say. What there can be no doubt about is that it demonstrates that a background app consuming CPU cycles is a non-issue. What matters -- in terms of user experience at least -- is memory.

Anonymous said...

I really appreciate what apple has done with the iPhone and iPad, but I am finding some of the limitations they are inflicting on userw and developers to be increasingly annoying.

I have to wonder though how big a deal some of this stuff is, really. It seems like Apple has left things pretty open in terms of enabling background processing for a wider range of use cases. What background/multitasking scenarios have people put forth that aren't fairly minimal extensions of the three supported use cases? Yes, I know that makes it even more frustrating, but it isn't exactly a surprise, is it?

People complained about all the things that Apple left out of the first iPhone, but it was hard to fault their execution on the things they chose to tackle first. With this release, they've enabled three important use cases that weren't well supported by push notifications, and the ability to suspend and resume apps quickly will help improve the experience when a user responds to a push notification.

It seems to me like the next steps are to add some sort owe ability to schedule periodic background task execution' and, I hope, allow push notifications to invisibly wake or restart background apps pot allow them to fetch new data and potentially create a local notification.

It does suck that it may be a year before any of that shows up.

mohitsharma said...

Thanks, as a iPhone developer, I totally agreed with you. You can not run long duration background task in iOS 4.x

BenSWoodruff said...

Couldn't the API that Instapaper would hope to one day use also be just as useful to other developers? Such as RSS reader apps and all the others that need occasional network access?

Maybe some of them already have their own APIs...I've seen lately that the official FB app and more recently the official Twitter app have push notifications. Are these capabilities limited only to these more official social apps or have they been expanded to all developers?

Thanks for the article!

Rus Bufton said...

Love the article, very insightful, and explains iOS and it's "multitasking" very well. As a former Apple employee, I'm not surprised at Apple's ridiculous marketing, and it just reinforces my decision to move over to Android. A far nicer and open system to use.

Halman Freud said...

It would be interesting to have a multitasking SO. Sometimes I like to run to apps on my Ipad and my ios 7 doesn't allow this.