"""On iOS when an app is installing from the app store and you put your finger on the screen, the installation instantly pauses until all rendering is finished.""" <- This is certainly not true. The update of the display for the installation progress might (...might) stop, as that's happening in the UI (aka, "main") thread of SpringBoard (and the event loop management might ignore incoming events that are not related to the touch event until after the gesture completes), but the installation itself is being managed by a background daemon (installd) and will not stop because someone is touching the screen. The operating system is /not/ doing something hilariously insane here, throwing out all computation on the device because someone is accidentally touching it.
> Threading Considerations Manipulations to your application’s user interface must occur on the main thread. Thus, you should always call the methods of the UIView class from code running in the main thread of your application. The only time this may not be strictly necessary is when creating the view object itself but all other manipulations should occur on the main thread.
"Drawing to a graphics context in UIKit is now thread-safe." http://developer.apple.com/library/ios/#releasenotes/General...
Some things won't work (notably UIWebView which also gets used in UITextView) but you actually can build a view in a NSOperation.
I think that the simple answer is that there's no simple answer -- which is what the earlier post was pretty much saying.
And as far as the author of this article goes…maybe he is off on the technical stuff, but he understands the most important, which is that UX is broken in Android for this, among a few other reasons.
Someone open a big report against AOSP? All versions, high priority; "UI Anmations Broken"
Well, it has everything to do with real-time priority, because in the case of Android, there is a clear priority inversion. That is, what should be considered the highest-priority work IMHO (updating the UI) is being delayed for other lower-priority work.
Absent other factors, the technically correct way of dealing with this kind of problem is using multiple threads and assigning the right OS priorities to them.
Maybe there are other constraints in iOS development that are causing the devs to wrestle with the main event loop instead.
In fact, it is this very property (that on iOS, all UI work must be done from the main thread) that often /causes/ UI lag, and yet somehow Android (where even this author admits using background threads for non-UI work "is the standard Android design pattern" in one of the comments on his post) is the one with the serious UI lag issues <- this mental contradiction is the key problem, and it would be awesome if someone (from Google or wherever) provides a strong explanation.
What you may mean by "the highest-priority work (updating the UI)" is really "the lowest-latency work". What we perceive as UI quality is the latency of sucessive events - is it smooth, and fast.
But OSs only give us a big hammer to manage this - priority of threads. Which is very indirectly related to latency. E.g. priority inversion, blocking i/o, the stupid habit of putting OS threads strictly ahead of user threads, and on and on, all impact latency in a way the programmer cannot constrain.
Experimental OSs have tried to use latency as the fundnamental scheduling metric. But each time a new mainstream OS is released, lo and behold it's based on stupid old priority.
So let's acknowledge the fundamental fact, that we're not being given the tools to achieve what we need, and everything we do is a workaround that's more or less successful. It all glitches under the right (wrong) conditions, all approaches are hacks of one sort or another.
For 4.x, if I remember correctly, it would pause the rendering. But I experimented a little then too, and it didn't pause the install at all - it'd just jump when you released.
Last time I tried it, Android did not let you create a thread with higher priority than the UI thread.
[0] http://developer.android.com/reference/android/os/Process.ht...
In Android, you can have a translucent popups from App#1 appear on top of any sort of screen of App#2. You can't have this on iOS. At all.
On the other hand, animations and scrolling are blazing fast on iOS without any need for superior hardware.
I honestly believe that this alone explains the "lacking" in performance that Android suffers from: it targets super high-end multi-core devices, with JIT compilers and optimizers that don't exist yet, in order to allow functionalities that are unclear to everyone of us.
Shameless plug: I made an app (1) that illustrates what iOS will never be able to do. The question is, will anyone ever need that sort of app on their phone?
(1) https://market.android.com/details?id=com.fairyteller.linkpr...
To be clear, we do this all of the time on jailbroken devices (where we have access to write apps with true multitasking, and can also just add code as required to SpringBoard itself, which is acting as the window manager): you just create a transparent UIView and put it in a new UIWindow; there are seriously no issues doing this.
In the end, every UIView is backed by a CoreSurfaceBuffer (I think "Core" got renamed to "IO" at some point, if you look this stuff up), which are managed by a kernel driver that allows processes to pass these buffers (which may be backed by video, not system, memory) to each other, and in the end they mostly composited (with alpha blending) in hardware.
1. All* rendering takes place on the main thread in iOS.
2. The main thread doesn't always have the highest priority. In fact, its priority level changes throughout an application.
3. There is more than just one reason iOS rendering is so fast. Here are two important ones:
a. Animation is actually the basis of the entire rendering system. On desktop Cocoa, the drawing system was a little dated. The mistakes learned from this system and the desire to have fast animation led to the Core Animation framework and the idea of "layers". The ability to quickly composite layers (without moving any data from between the CPU and GPU) and only redraw when necessary is huge.
b. The batching together of drawing updates at the end of an event instead of on an as needed basis allows for huge performance gains.
* It is possible to draw in a background thread, but is reserved for particular situations (maps, web content, etc.). Table views do not fall into this category.
Will OSX ever catch up to Windows for games? Maybe. Some game companies take the approach of writing everything in OpenGL to make it easier to port between systems, writing a layer of native code to support their cross-platform code.
However, some studios use DirectX which is windows-only. The popularity of OSX and iOS will only increase the pressure on game developers (and engine developers) to write code that is easier to port.
Is this just the difference between Java and Obj. C?
What would such a re-write look like, from a practical coding point-of-view? Couldn't this be done in a way that is transparent to the calling code, or would there have to be a fundamental re-write of the SDK, i.e., the UI thread no longer be the main thread?
Some applications may run fine, but I bet you will find a lot that do not, even ignoring timing differences that may cause problems with games.
(In other news, I just ordered my Galaxy Nexus yesterday and am rather looking forward to it. Can you tell?)
The trick is that there is effectively only ever one model iPhone / iPad at a time -- so right now it's the 4S, for example, that captures all the mindshare and forms the basis of comparison. Legacy iOS devices simply cannot keep up, and certainly do not maintain the buttery-smooth experience that people identify with iOS. But nobody appreciates this, because legacy iOS devices aren't an active force on the market. Android devices, meanwhile, come in many hardware configurations, some of which are much more analogous to my old laggy 3G than to the latest iOS hotness.
This isn't an excuse: it just means that Android has set a harder task for itself than iOS has. But that's no reason not to succeed at that task. 15 years ago, my hand-built BeOS box gave me an unbreakably buttery UI -- even during obnoxious geek demos such as simultaneously playing 30 different videos in 30 different windows -- so there's no reason that ANY computing device, even a very cheap one, should not be able to match that performance today. This article gives a good insight into how Android is failing to do so, and what some of the solutions might be.
That's not the "only" fair comparison. The 3G is a three and a half year old device. It's also severely memory constrained and probably shouldn't have gotten iOS 4 to begin with. You're certainly running into paging issues: iOS doesn't have a backing store for virtual memory, but it will drop and reload read only pages out of flash storage when it's memory constrained.
The iPhone 4 is almost 18 months old and compares quite favorably with year-newer Android devices on the UI responsiveness front.
I have a 3G and like you said it should have never gotten iOS 4. But the 3GS is just fine.
I have a Droid bionic (second Android phone) and a Kindle Fire. What lag should I be suffering?
Other lag is also present in the initial part of scrolling. Android takes a bit longer than iOS to respond to your fingers' movements. Its on the order of milliseconds, but it is noticeable if you compare it to an iOS device.
A lot of Android's rendering takes place on the CPU and a lot of it is small batches of serial work that isn't very well suited for concurrent execution on multiple cores.
I love the open discussion about Android's weakest point and I appreciate opinions from all side, in particular those from inside Google -- but this uncoordinated communication on G+ addressing problems w/o delivering a solution damages Android's image to some extent.
Still, I don't have experience with iOS devices, but my Nexus S tends to be so laggy at times that apps crash frequently. (I had attributed it to GC).
This sounds more like poorly written apps than an issue from the article.
For example if you are scrolling a list view and it slows down to the point of crashing, the application probably isn't caching views or has a memory leak (application authors fault).
If your device gets sluggish and you get miscellaneous force closes I would look for applications with background services that are doing more work than they should be.
Nonetheless, while Android continually works to smooth out the rough edges -- helped along by the march of technology -- this is something that is a bit overblown: Minor jutters of the interface is something that primarily irritates people as a relative thing, not as an absolute thing.
If you are a developer or a reviewer and you regularly use an iOS device and an Android device, the difference is evident and jarring. If you're an end-use it quickly disappears and is a non-issue. It just isn't a real problem for end users.
It's the same as getting an upgrade to your PC, a new video card, etc. You were perfectly happy before, but relative to your new reality the old one seems subpar, and you overestimate how much it interferes with your enjoyment of the device.
On iOS, in the span of a short morning I can hook up a button or slider to send out MIDI messages over WiFi to my MBP and route it to any device I want; I have no idea how to get the equivalent setup on Android. What if I want to decode an mp3 and process the resulting audio? I can tell you two ways on iOS, I know of a vague direction that might work for Android. You have to dive down into the NDK to do it, too. What about compositing video? Well...
Seriously, here is AVFoundation on iOS. This is a high-ish level Obj-C interface for mucking about with AVAssets, which can be audio or video:
http://developer.apple.com/library/mac/#documentation/AVFoun...
This is just a single library dedicated to a single level of abstraction. Video composition, audio mixing, playback control and monitoring... there's a lot going on just here. You've also got CoreMIDI, AudioQueues, AudioUnits/AUGraphs, MusicPlayer... they're not easy to pick up, but they're there and they can do serious work.
Here is what you can do in Java on Android:
http://developer.android.com/reference/android/media/package...
You can play encoded media, you can capture a raw input stream or direct it to an encoded file, you can play raw PCM... that's it. Really. To my knowledge, I'm not exaggerating when I say that - I'd be in debt to whoever proved me wrong, so please do!
For graphics on Android, there's usually something analogous you can get by with. For audio, though, it's just... not there at all.
[0] https://market.android.com/details?id=xian.bubbles&hl=en
From what I understand, Android will only give an app a large buffer, so when the app starts filling up that buffed, it may take a little while for the 'playhead' (is there a more technical term?) to get around to playing those samples.
On iOS however, an app can request a much smaller sample buffer, so there's less lag time between when an app fills that buffer and when the samples actually get played.
Apple, on the other hand, decided that a touch-based interface was the way to go. As such, Apple designed iOS to make rendering in a special, real-time priority thread to ensure responsiveness.
Likewise, a good low latency sound system with MIDI support was added to iOS not because Apple correctly predicted that smartphones and tablets would be popular for music production, but because those were features already present in OSX.
AFAIK, the Android designers started out making a Blackberry clone, and creating a similar software stack would have been a lot more work at a time when the competitors were all running 2D GUIs with no GPU acceleration or fancy animations.
Er, there are a lot of Android devices that are keyboard and trackball powered.
There is definitely a different philosophy, though. The Android approach was that it was better to be correct -- if you scroll a page or a webpage, that what scrolls into the viewport needs to be correct, while iOS happily scrolled in a checkerboard. I prefer the stock Android approach (some devices, such as the GS II, sub in the "better to be fast" approach, giving smoother superficial interactivity) so long as there is enough hardware that the result isn't too painful.
How do you define "correct"? The "correct" behavior is dependent on what you're trying to achieve. What you're trying to achieve should be defined with reference to the user: what will make the user happiest?
In a multi-touch interface, where you're trying to maintain the direct manipulation illusion, preserving "feel" at the expense of showing the rendered content a split-second earlier is almost certainly the right trade-off. The user will chalk the checkerboard up to page loading and their internet connection. They'll chalk hiccups in manipulation up to the device itself.
Android started as a platform trying to out-Blackberry RIM. When the iPhone was released in 2007 they switched to a model of trying to out-do iOS.
I'm not sure Android is clearly succeeding. Samsung, etc. are succeeding. If they switch to a superior OS (Windows?) but keep similar pricing I suspect only a very small core of hardcore Android fans would remain.
Basically, I'm an existence proof against your argument (and now a happy iPhone owner too).
That wasn't what I was talking about. I'm talking about almost imperceptible, frame-or-two jitters that is the current state of Android on virtually any contemporary device. The top selling Android devices are all "buttery smooth" in the perception of their users, even if relative to an iPhone it is herky jerky.
per your quote: "It's the same as getting an upgrade to your PC, a new video card, etc. You were perfectly happy before, but relative to your new reality the old one seems subpar, and you overestimate how much it interferes with your enjoyment of the device." Doesn't quite make sense in this market though. It's all about having the fastest, shiniest, device. And if you can't keep up or deliver ever demanding performance increases, you die. If good was good enough, and we didn't care that the next best thing was only marginally better, we'd still be using punch cards.
It's not even about that. It's about something usable and working as expected. I have an Android smartphone (LG P350) with bundled Facebook and Twitter, both of which I never use because they're too heavy for the phone. They barely work, they hang up for minutes, and crash my homescreen. And if I try to sync them, it usually ends with me taking the battery out after few minutes of staring at shining screen of a totally non-responsive (hardware buttons included) phone. Not to mention that once or twice an incoming call was too heavy for that phone to handle, => battery removal operation necessary.
Next time before choosing Android, I'll carefully test current devices, and switch to iPhone if I ever find a trace of UI lag.
However to the relative thing, to most smartphone users the things that matter are can I use Facebook, how is the picture quality, can I share videos, etc. Others want a keyboard, big and bright screen, etc. To normal users -- the ones buying the overwhelming bulk of devices -- this just isn't the big issue that it is on tech boards. It just isn't.
So I'd put that up to a plain old bug (albeit a really frustrating one, and knowing the Android ecosystem one unlikely to be fixed), not a platform misfeature.
That most certainly does bother me, and I've yet to discover how to disable it so it simply reacts immediately.
Except when they're trying out different devices looking to buy one.
Also, to a certain extent people put up with stuff like this because they don't know it can be better. E.g. Windows's shitty move/resize for all those years. But do you think, in the face of OS X, Windows could've continued to do without compositing up to now?
Yes, it is. When people ask me how I like my new smartphone, I always say to them: "I like the idea behind Android, but it sucks in use; this smartphone is too weak to handle the basic OS, which makes using it terribly annoying for most of the time".
Yes, it sucks. There are constant lags in everything from button presses to scrolling. Main screen gets killed by the OS every few minutes, and it takes it 30 seconds to load up and become usable. Activating Wi-Fi and letting Facebook and GMail sync at the same time equals to several-minute long hang followed by me plugging the battery out. The phone occasionally hangs when receiving calls, and often when trying to dial.
Yes, for me, Android phones are piece of crap. I use mine, I put up with it, but it's not pleasant. It's damn annoying every single day.
It seems to me race conditions are no more or less of a concern for rendering animations than updating data -- and probably less, actually, since there's probably not much contention for animation resources, and if there is contention, synchronization of access to drawables should be straightforward.
That would change the rules from "model updates and screen redraws never run concurrently" to "...will typically run concurrently". I think you agree that is asking for problems.
Of course, it is possible to adjust the system to apply different rules to different apps, but then apps would have to be changed to advertise "I am fine with running updates on a different thread". I think newer versions of Android already have some of that.
The task manager/switcher is a child of the home screen. This overloaded functionality makes sense that you go to the home screen immediately and if you happen to click again it goes to the secondary mode.
Vlingo on the GS II has nothing to do with the home screen. It is its own world.
Should they have made the very first click instantly go to the home screen anyways (which could involve a lot of busy work given how rich an Android homescreen can be)? Good question. I don't think the two are directly comparable however.
Also, it is my understanding that surface compositing is done in hardware using surface-backed textures, with any software rendering of those surfaces being done on the main UI thread while responding to messages such as drawRect, using CoreGraphics (not CoreAnimation). The only thing that gets shoved to background threads are, AFAIK, animations that are specified in code but then "set free" into the CoreAnimation backend.
I thereby don't feel like these comments adequately defend the statements made in the article: the things it claims are benefits of iOS's graphics architecture either A) work the same on Android (per the post it is responding to from the Android developer regarding the myths of Android hardware surface compositing) or B) actually happen in software on the main/UI thread on iOS. I think we need to look elsewhere for the real cause of Android's horrible touch response. ;(
Obviously you never went through tunnels. When I am playing a 100% offline game (without internet access) and my bus goes in the tunnel, everything stops. Who cares about this "game" when I have tons of networking to do. Networking takes precedence over animation so what happens is any touch events or animation or anything is heavily delayed.
What about the phone? When the call is ending, it can't render a UI update that the button was touched, thus just a delay. It even delays processing the next input event until after the screen switches states. End result? I make a call when I try to hang up or vice versa. Point being that these problems are not exclusive, but the iOS solution is significantly better for these edge cases which are the ones that cause the biggest headaches, they still happen in iOS but very infrequently vs consistently bad every other time.
So that an UI Update that is waiting for hardware can be delayed and the next UI update in the loop can be processed.
I dont seem to recall any such pattern for Java main thread UI Updates.
dvmLockMutex(&gDvm.heapWorkerLock);
//BUG: If a GC happens in here or in the new thread while we hold the lock,
// the GC will deadlock when trying to acquire heapWorkerLock.
if (!dvmCreateInternalThread(&gDvm.heapWorkerHandle, "HeapWorker", heapWorkerThreadStart, NULL))
{ dvmUnlockMutex(&gDvm.heapWorkerLock);
return false;
}// Block until all pending heap worker work has finished.
void dvmWaitForHeapWorkerIdle() { int cc;
assert(gDvm.heapWorkerReady);
dvmChangeStatus(NULL, THREAD_VMWAIT);
dvmLockMutex(&gDvm.heapWorkerLock);
/* Wake up the heap worker and wait for it to finish. */
//TODO(http://b/issue?id=699704): This will deadlock if
// called from finalize(), enqueue(), or clear(). We
// need to detect when this is called from the HeapWorker
// context and just give up.
dvmSignalHeapWorker(false);
cc = pthread_cond_wait(&gDvm.heapWorkerIdleCond, &gDvm.heapWorkerLock);
assert(cc == 0);
dvmUnlockMutex(&gDvm.heapWorkerLock);
dvmChangeStatus(NULL, THREAD_RUNNING);
}Android runs on Linux. Linux uses Futexes (Fast Userspace Mutexes) for locking abstractions like semaphores and mutexes. From Wikipedia -
"A futex consists of a kernelspace wait queue that is attached to an aligned integer in userspace. Multiple processes or threads operate on the integer entirely in user space (using atomic operations to avoid interfering with one another), and only resort to relatively expensive system calls to request operations on the wait queue (for example to wake up waiting processes, or to put the current process on the wait queue). A properly programmed futex-based lock will not use system calls except when the lock is contended; since most operations do not require arbitration between processes, this will not happen in most cases."
I'd say if anything this argues for a total absence of correlation with user experience, no?
Source? There have been many reports of Android phones outselling the iPhone, but I am not familiar with the ones about Android devices outselling iOS devices (iPod touch, iPad, etc.)
At least cellphones is a more like-for-like comparison.
IMHO, iOS users spend more on apps because iTunes is better than Android's Marketplace - this may have been a deliberate decision by Google nonetheless. Did you know that I am not allowed to sell Android apps in the Marketplace because my country is still not approved for registering a Google Merchant account? That's right, it's almost 2012 and while I can sell apps on iTunes, I can't on Android's Marketplace. However I have no problem integrating AdMob in those apps. So it's like Google wants ad-supported instead of paid apps, which considering their main business model it isn't that shocking.
However, you can't say that Android and its UI is not a success.
thread management they're required to trap into the kernel to acquire a mutex.
Of course GC is handled by the VM. That's not the point here though - the point I thought you made was that the GC uses mutexes and they're required to trap into the kernel. (At least that's how it reads above) That's not the case on Linux. GC uses mutexes which are implemented as futexes[1] that stay in user space for most of the time.
[1] http://www.mail-archive.com/uclibc@uclibc.org/msg02787.html
// Grab a plain mutex.
INLINE void dvmLockMutex(pthread_mutex_t pMutex) {
int cc __attribute__ ((__unused__)) =
pthread_mutex_lock(pMutex); assert(cc == 0);
}and here's pthread_mutex_lock.
int pthread_mutex_lock(pthread_mutex_t mutex) { if (mutex->kind == PTHREAD_MUTEX_NORMAL) { if (atomic_exchange(&mutex->lock, 1) != 0) { while (atomic_exchange(&mutex->lock, -1) != 0) {
if (wait(mutex->event, INFINITE) != 0) return EINVAL;
}
}
}
else
{
pthread_t self = pthread_self();
if (atomic_exchange(&mutex->lock, 1) == 0)
{
mutex->recursion = 1;
mutex->owner = self;
}
else
{
if (pthread_equal(mutex->owner, self))
{
if (mutex->kind == PTHREAD_MUTEX_RECURSIVE)
mutex->recursion++;
else
return EDEADLK;
}
else
{
while (atomic_exchange(&mutex->lock, -1) != 0)
{
if (wait(mutex->event, INFINITE) != 0) return EINVAL;
mutex->recursion = 1;
mutex->owner = self;
}
}
}
}
return 0;
}and here's an excerpt of dalvik/vm/Thread.c
Notes on Threading
All threads are native pthreads. All threads, except the JDWP debugger thread, are visible to code running in the VM and to the debugger. (We don't want the debugger to try to manipulate the thread that listens for instructions from the debugger.) Internal VM threads are in the "system" ThreadGroup, all others are in the "main" ThreadGroup, per convention.
The GC only runs when all threads have been suspended.
...
Although I don't understand how the memory management makes use of mutexes (once a (any?) thread realizes that the GC needs to be run, how does it wait until all threads have reached a safe point?), and I don't have time to check ATM.
[1] http://www.insomniacgames.com/tech/articles/0807/files/multi... mentions the pthread_mutex_lock and unlock code including an implementation of atomic_exchange
The interface problem with Android might come in to play when people are considering their second smartphone, and devices are a lot faster these days. Of course, no one should need a dual core or quad core CPU for a smooth experience on their phone.
I have an iPhone 3GS and a Galaxy S which recently upgraded to Gingerbread. The iPhone experience is indeed more "smooth", however that doesn't bother me because the advantages that my Galaxy S gives me outweigh the smoothness of the iPhone.
As an example, on my Galaxy S I was free to install a calls / SMS blocker. You can blacklist certain numbers and then it's as if those numbers don't exist - not only it blocks the calls / messages, but it also removes all traces from the logs. Last time I checked these types of apps where banned from iTunes. On Android it isn't so cut and dry either, as these apps are using private APIs that aren't documented, however they are allowed on the Marketplace.
Another example would be the kickass integration my device has with my Google Apps account. For instance all my phone numbers are synchronized with Google Contacts. And don't get me wrong, I'm sure this is only a matter of preferences and I could probably do the same thing on the iPhone, however this works both ways and I'm having an easier time with my Android to do what I want.
The only annoyance I have with my Galaxy S is the slow upgrade cycle. It will probably take forever for Samsung to deliver to me an upgrade to Android 4. Which is why my next phone will be a Google Galaxy Nexus, or whatever blessed phone will come next after it.
Do they? The big Android surge only came in the last year, so the vast majority of Android users are on their first.
Also, the way a queue prevents two consumers from popping off the same element is the same way a mutex is implemented.