Android Dalvik VM performance is a threat to the iPhone

One of the peculiarities of Apple is that they have set themselves down a path where every Apple developer needs to learn Objective-C (and C/C++) to build applications for their platform.  The biggest characteristic of Objective-C vs Java is dynamic dispatch. At runtime Objective-C can send arbitrary messages to objects and they may or may not respond to them.  This has the nice property that you can write code that is very dynamic and loosely bound but it also has the property that method calls in Objective-C are very slow and the more code that you write in Objective-C instead of in C/C++ the slower your codebase becomes.  Up until Android 2.2 (Froyo) the JVM (really a Dalvik JVM for licensing reasons) on the Android platform was playing with one hand tied behind its back.  Different from desktop/server Java, the JVM was still an interpreter, like the original JVM back in the Java 1.0 days.  It was very efficient interpreter but an interpreter none-the-less and was not creating native code from the Dalvik bytecodes that it uses.  As of Android 2.2 they have added a JIT, a just-in-time compiler, to the stack that translates the Dalvik bytecode into much more efficient machine code much like a C/C++ compiler.  You can see the results of this in the benchmarks of Froyo which show a 2-5x improvement.  As they add more and more JIT and GC features that have appeared in HotSpot, JRockit, etc, you will likely see even more improvements over time — without having to change or recompile the 3rd party developed software.

This wouldn’t be that big a deal if Android software wasn’t already approaching the speed of the Apple iPhone even when running its applications through the interpreter (see the HTC EVO 4G running 2.1).  This is likely going to mean that 3rd party developer applications created for Android, running on the same hardware, is going to be faster than the same code written against the Objective-C libraries that Apple provides for the iPhone.  You’ll be able to get more done, have smoother user interfaces and all around build more powerful applications easier.  A better experience for the user and the developer on Android is a bad thing for Apple.

The final issue that Apple has is that far more people know and need  to know Java than Objective-C.  Except for their platform, there is no need to ever learn it.  The tool chain is much more robust, information is much easier to come by, garbage collection is available, and there are thousands more libraries written in Java than Objective-C and far more portable libraries than are written for C/C++.  You might argue that you can always drop down to C/C++ code to make up for the lost performance of using Objective-C (at a significant cost development-wise).  You can do that, except places where you need to make a call into Apple’s Objective-C runtime libraries or where you want to write callbacks from those libraries. Those are mostly Objective-C libraries and use the dynamic dispatch mechanism which I showed in 2004 was very much slower than Java.  I’d really love to see the whole computer language shootout written with Objective-C calling conventions just to show how much slower it is at that level.

Obviously performance is not the only consideration, but it is a big one.  Android has other issues like a fragmented operating system base, hardware feature base and a more complicated user experience.  All those things will conspire to hold it back but I think we can see the writing on the wall that Android is going to dominate iPhone market-share wise which will eventually make it a more attractive platform business-wise.

Update: Just so people don’t get the wrong idea, I am a rabid iPhone user and develop for the iPhone first.  This blog entry is to call out a threat that Apple should take seriously.

Update 2: Alright, you win. Don’t worry about competing with Google & Android on performance. It probably doesn’t matter that much for the user experience.  Especially don’t fix obj_msgSend() with a JIT/LLVM, that would be crazy.

This entry was posted in Apple, Java, Technology. Bookmark the permalink.
  • http://www.javarants.com spullara

    I didn't suggest switching the iPhone to Java. I think Apple needs to focus on performance of their Objective-C runtime and their core libraries or face an unnecessary performance gap.

  • http://www.javarants.com spullara

    I don't imagine anyone, even Apple, mistakes NSAutoreleasePool for garbage collection.

  • elasticthreads

    “This wouldn’t be that big a deal if Android software wasn’t already approaching the speed of the Apple iPhone even when running its applications through the interpreter (see the HTC EVO 4G running 2.1). “

    I like how, to compare the performance of two software platforms, you use different generation hardware: a phone that hasn't been released for sale yet (the EVO) to a year old phone (assuming you're talking about the 3GS) that is approx. a month from being replaced by faster hardware.

    I bet Obj-C runs faster on my 2009 Mac Pro than Java does on a Pentium…

  • http://www.javarants.com spullara

    Ok, then everything is native code.

  • Zabbot

    Some people think using malloc/free equates to “garbage collection”. They are wrong, but there you go. Technically, there's a distinction is between 'automatic' versus 'manual' garbage collection. Pragmatically, no one except Lisp graybeards uses garbage collection in that way.

  • Chris

    I'm not convinced about your argument about performance, but i'm 200% agreeing with you about the foolishness of apple to stick with an obscure language obj-c, versus android with java which pretty much every developer in the world has had exposure to. I'm currently learning obj-c and iphone development, it's very difficult to wrap my head around, coming from a c#/java/ruby background.

  • CoderCanuck

    Hate to break it to you all, but there's a pile of people that learned to type that way and it's in muscle memory.

  • name

    Good to see that, even in a world with big, successful companies like Apple badmouthing crude middleware layers and preaching the virtues of actually understanding the platform you are coding to, Java is still out there, making it possible for any uninformed idiot to create “software”.

  • name

    Good to see that, even in a world with big, successful companies like Apple badmouthing crude middleware layers and preaching the virtues of actually understanding the platform you are coding to, Java is still out there, making it possible for any uninformed idiot to create “software”.

  • http://reedmorse.com Reed Morse

    If only the Android development toolchain were half as nice as the iPhone's… The Android SDK tools integrate terribly with Eclipse.

  • http://reedmorse.com Reed Morse

    If only the Android development toolchain were half as nice as the iPhone's… The Android SDK tools integrate terribly with Eclipse.

  • CoderCanuck

    I think you need to examine the details on JIT optimizations. A dispatch that passes static analysis and can be inlined IS inlined. It can later be unwound (since about 1.4 or 1.5) if a dynamic mod is made via introspection or the like. Objective-C doesn't have that level of dynamic inlining currently available, but as noted before, the LLVM work and features in Objective-C 2.0 that came out (including Garbage Collection, but not on the iPhone yet) are pushing Objective-C forward quite well.

    I've coded a long while on Java, and am increasing my work in Objective-C. They are different languages, and some things in Obj-C are actually quite good and cleaner than Java, others are not. If you want speed though, you are working in C with object extensions, and you need not always do a method call if it's speed critical, you make it a function call that, as Java will do, will compile in-line. But you lose dynamic capability in that case. Java has an edge with a very mature and capable runtime, Obj-C is still C in the core, and if you aren't taking advantage of the runtime, you're able to go fully optimized C code.

    I don't see a clear winner in either of them at this point. There's advantages and issues with both. And excuse my double spaces after periods. It's an old habit and I'm not about to remove them at this point in the post. I also put extra whitespace in my code for readability. ;-)

  • CoderCanuck

    I think you need to examine the details on JIT optimizations. A dispatch that passes static analysis and can be inlined IS inlined. It can later be unwound (since about 1.4 or 1.5) if a dynamic mod is made via introspection or the like. Objective-C doesn't have that level of dynamic inlining currently available, but as noted before, the LLVM work and features in Objective-C 2.0 that came out (including Garbage Collection, but not on the iPhone yet) are pushing Objective-C forward quite well.

    I've coded a long while on Java, and am increasing my work in Objective-C. They are different languages, and some things in Obj-C are actually quite good and cleaner than Java, others are not. If you want speed though, you are working in C with object extensions, and you need not always do a method call if it's speed critical, you make it a function call that, as Java will do, will compile in-line. But you lose dynamic capability in that case. Java has an edge with a very mature and capable runtime, Obj-C is still C in the core, and if you aren't taking advantage of the runtime, you're able to go fully optimized C code.

    I don't see a clear winner in either of them at this point. There's advantages and issues with both. And excuse my double spaces after periods. It's an old habit and I'm not about to remove them at this point in the post. I also put extra whitespace in my code for readability. ;-)

  • http://www.javarants.com spullara

    I have high hopes for LLVM. I'm hoping that it will close this gap.

  • Willie Abrams

    FWIW, I think invocation speed is a terrible benchmark. Besides, I agree with another commenter that your benchmark is testing the low-level libraries as much as dispatch…

    I went back and read your original article (2004) about Java, Obj-C and C speed. You concluded that Java was faster than Obj-C. You also concluded that Java was faster than C. I built put your JavaBenchmark into a command line tool and ran it. I ran the C benchmark again with GCC, and I ran it through clang. Here are results 6 years on…

    210690 : gcc 4.2.1 -O3
    306842 : javac 1.6.0_20
    446515 : clang 1.0.2 -O3

  • CoderCanuck

    Native code I will posit is machine instructions directly executed by the CPU in question. Objective-C is native code in that way, and the dispatch is done via function calls through a lookup table, not unlike the way C++ lays out, but the table can be altered at runtime. Still, all this is done in machine-code that is native to the CPU.

    Contrast Java, where non-JITted code is in an intermediary representation (byte code) until the JIT analyzes and opportunistically or deliberately depending on circumstance converts it to native machine code. Byte code is running through an interpreter, that jumps to direct execution when it hits a JITted segment of instructions. Objective-C is all native machine code, and the dynamic aspects are done by shifting things in those memory structures and code paths in native machine code. There is no byte-code in the gcc compiled objective-C.

  • http://www.javarants.com spullara

    This is exactly what I would like to see. Is there any evidence that they are going to go to this level with Obj-C or will the continual refrain be “rewrite in C/C++ for speed”?

  • Ladd

    You're mostly measuring string comparison performance, not method dispatch. Shark will easily show you this for the Objective-C side.

    Certainly, it could be argued that the NSString compare: method is somewhat slow, but this hasn't ever been a problem for me in practice.

  • phutwo

    You're comparing objc's message passing versus Java's function calls? Why don't you compare objc's function calls (C's function calls) versus Java function calls? You don't have to use objc's message passing, just make a direct call if you need it, those objects are just pointers. Java may have a slight advantage under rare cases as it can JIT into inlined. In those cases you can inline C's function calls as well.

    But you're missing the forest in the trees. In most normal GUI programs, you make a few thousand messages and that amounts to 0% of the run time. On an iPhone or Android, most of your time spent would be in library calls, both of which are native.

    Neither objc or java really matter in GUI applications. In high performance gaming applications, objc's advantage is it can use native instructions of the hardware (and precise control of memory layout), for instance the neon arm extensions or any new hardware instructions Apple chooses to implement in the future (Now that they can move functionality between soft and hardware freely). With Java, that has to be abstracted out into a library or use the NDK.

  • Danny Woods

    Unless your application has distinctly non-repetitive usage patterns, the JVM (or CLR, for that matter) will be on-par with C for a good many tasks. I wrote a video decoder in Java for a proprietary codec last year, and surprised the developer of the codec by outperforming his reference C implementation and being easily as fast (maybe a little faster) than his drop-to-MMX optimised version. Why? Because a JVM with a JIT can analyse how your code is running, not just how you or your compiler envisioned it running when the pre-optimised blob was written to disk. The JIT can also decide to use architecture-specific acceleration features (MMX, SSE) without you ever even knowing assembler; if you want to compete with that in C you'll need to cut-off all users below a certain CPU capability threshold and have a *very* good compiler. Frequently called methods that are not overridden in subclasses generally have monomorphic rather than polymorphic dispatch, avoiding a vtable lookup that a virtual method in C++ hard-codes at compilation. Small methods are often inlined into their callers when the running system demonstrates that it is required.

    As for developer time: he spent a non-trivial amount of time writing and tweaking the assembler for the block transforms used by the codec. I just translated the vanilla C versions.

    The downside? Memory, of course. While my decoder was as fast as the optimised C version, it consumed far more memory, even after a several passes through the code minimising the number of allocations (all that did was give me a very shallow memory growth curve and fewer garbage collects). Also, not all JITs are equal. Just because Dalvik now has a JIT doesn't necessarily put it on a par with modern HotSpot implementations.

    There's also the lack of control. You can't shave cycles off of a tight loop by hand-crafting some assembler that takes advantage of some high-level knowledge that you, the programmer, have.

    As to your last point, on battery life: the JIT will help here. Code that tries to run as fast as possible will accomplish what it's trying to do sooner; code that's task driven will accomplish those tasks with less load on the CPU. Both mean less of a drain on battery.

  • Pingback: Android :: TechMiso

  • Pingback: Duncan Davidson on Android’s Virtual Machine Performance as a Competitive Factor Against the iPhone | reabilita.me

  • Pingback: Duncan Davidson escribe sobre el rendimiento de la máquina virtual de Android como ventaja competitiva contra el iPhone | Daring Fireball en español

  • http://www.music-piracy.com Matt

    Dlavik is a threat to android, and has been since day one. Let's honestly look at the stupidity of this post. You are arguing that a native application dev environment that's more robust than androids sdk, faster, and quicker to program in is somehow in trouble from a slow ass busted and might I added perfectly retarded register based vm.

    Yeah ignoring the merits of dlavik as a VM, let's just right off the bat point out you just said that iphones ( generally faster processors than android designs ) are now facing a threat from a VM… on an embedded device.

    That doesn't make any sense. It's incomprehensibly stupid. It's like saying “Dlavik sucking less makes it AWESOME”. No it doesn't. It makes it less shit. But at the end of the day it's still shit.

    As long as android relies on dlavik they will suffer in the app war with apple. And that's obvious when you talk to developers, and when you look at numbers.

    Also, you realize that Sun's commitment to Java is lapsing as they lose all of their core devs right? The language that couldn't succeed since it's flawed inception in the 90s is in rapid decline. Largely thanks to google btw. So saying that using Java as a language is somehow superior to objective C, even from a preference point is lacking in some attachment to reality. Objective C is a cleaner language that's easier to read, and work with. It's got a lower learning curve, runs faster, and has libraries that don't suck. Apple's implementation of it is one of the best on the face of the earth. You look at android's SDK, and even there NDK and it makes you want to stab people in the face.

  • Strangway

    A *lot* of people learned to say “backslash” when talking about forward slashes. It's bad learning. That guy is right, stop using two spaces after a period. Unlearn.

  • http://alastairs-place.net alastair

    Your post from 2004 is wrong, since you aren't measuring method invocation overhead at all. In all of your tests, you're actually measuring the performance of the string comparison API. You can see that this dominates the results easily enough. Also, I'm suspicious about the validity of the test because I think the Java compiler is optimising away code that should be being timed.

  • http://www.mcubedsw.com Martin Pilkington

    There are 3 things you are missing:

    1. objc_msgSend is fast enough that this isn't really relevant. The bulk of performance issues in both languages is in their libraries.

    2. Java method calls are incredibly inflexible. The reason Apple goes with Obj-C is because dynamic dispatch, despite being a bit slower, is far more flexible and allows for design patterns that allow for developers to write less code to do the same thing. Obj-C is sacrificing a bit of runtime speed (which is largely irrelevant on even mobile phones) for the sake of faster development time and more elegant code. Plus you get things that you can't do with a basic method call. Unless I'm mistaking, you can only call a method on an object in the same process. With Obj-C you can send a message to an object on the other side of the planet.

    3. Ultimately this doesn't affect users. Java and Obj-C have been side by side on the Mac for years. They didn't care that Java could invoke a method faster than Obj-C could. What they cared about wast that the apps written in Obj-C had far better user experiences and integrated better with OS X. You can throw all the low level comparisons around you like, ultimately users care about having a fun, responsive and useful application and couldn't care less about how a developer created it.

  • Niklas

    “garbage collection is available”, as it is in Objective-C, not on the iPhone currently, but that;s not a Java advantage since Objective-C has it on the Mac.

  • Jon Hendry

    Autorelease pools are a form of reference counted memory management, not garbage collection.

    And it goes back to about 1995, not “since Leopard”

  • http://www.javarants.com spullara

    There is reason only one company uses Objective-C and it is not its awesomeness.

  • Pieter

    If performance matters, Dalvik is doomed. There will always be a penalty for byte code. Either due to to interpretation itself costing time or due to performing JIT, itself costing time, forcing bookkeeping and taking memory for the compiled code that could otherwise be used for caches or just keeping a larger working set in memory.

    Separate from that, I think you misunderstand the amount of function calls done using the objc_msgSend system in a real application.

  • Pieter

    I don't believe the 12G invocations per second you claim for java, I think you have been had by your JIT compiler.
    I do believe the 116M invocations per second for Objective C…
    See my comment on Stefan's site…

  • Steven

    Just out of curiosity? Do you like uneducated people as well? A single space after a period/full stop simply looks annoying.

  • http://blog.chrissaari.com/2010/05/27/the-traffic-cop-pattern-or-why-java-vs-obj-c-isnt-really-that-important/ Chris Saari
  • http://kenkinder.com/ Ken Kinder

    Performance aside, you mention that a lot of developers already know Java and that puts them in a position to develop for Android. Unfortunately, that's only sort of true. While Android uses the Java language, even the more basic Java libraries are missing and replaced with Google ones. All those Java developers who trained for Sun's idea of Java are going to have to relearn everything but the language itself.

  • http://www.mcubedsw.com Martin Pilkington

    It is wrong to suggest that you have to be a fanboy to like Objective-C. I can see several flaws in Objective-C and things that annoy me a lot. However, it is an incredibly powerful language. The dynamic dispatch isn't bolted onto C, it is a runtime build with C. It is no more bolted on than stdio is bolted onto C.

    Now for some, including me, Objective-C *is* a lot easier to read and a lot cleaner. You can more easily see nesting thanks to the square brackets, you have interspersed arguments which makes methods far more self documenting and you can do more in less code thanks to the dynamic dispatch.

    The issue is, you are complaining about Obj-C being “slow” because of dynamic dispatch. I can show you 100s of Obj-C apps that run perfectly fine despite dynamic dispatch and 100s of Java apps that run slow even with the static method calling. Hell, have you tried an Android phone and iPhone side by side? It is ridiculous how slow the Android is in comparison at times, yet it is selling reasonably well.

    The fact is that these things are largely irrelevant and the majority of performance problems come from APIs or just bad code. The largely insignificant runtime cost of dynamic dispatch is more than made up for by the very significant savings in development time that a dynamic language affords you. Users don't care about invisible speed issues, they care about real speed issues. Developers don't care about getting every last little bit out of their code, they care about writing less code, faster. This is why we write in Objective-C, C, Ruby, Python, C# and even Java instead of Assembly. About the only time you *really* need to drop down to C and where Obj-C is “slow” is when you need realtime processing, such as audio, in which case almost anything bar C is likely to be too slow and sometimes C itself can be.

  • Pingback: Android vs. iPhone Performance | Software Testing Blog

  • Pingback: Android vs. iPhone Performance | Mobile App Testing

  • sam

    Yeah this “poor Java developer” makes a shitload of money writing Java and that won't change for a very long time. In fact, I'd bet I make more as a “poor Java developer” than just about any staff iPhone dev out there. All this and Java is going nowhere. It's still dominates the market and will for decades to come.

    Finally, Java may suck as a language but so does Obj-C. Looking at O-C code is like looking into a code museum. So spare me.

  • Pingback: Copland 위기, 다시 올 수 있다