But is this even a debate? Wouldn't you expect a compiled, manual memory managed, language to be faster than an interpreted language with garbage collection?
That's an interesting benchmark, and I'd need to dive into the details to see what is going on. Perhaps there is some sort of JIT slow path. I would not expect method-heavy Objective-C to beat JavaScript. In general:
> But is this even a debate? Wouldn't you expect a compiled, manual memory managed, language to be faster than an interpreted language with garbage collection?
Objective-C is not compiled in terms of method dispatch, nor it is manually memory managed. Instead, all method dispatch happens through essentially interned string lookup at runtime, backed by a cache. Objective-C also has a slow garbage collector--atomic reference counting for all objects. (Hans Boehm has some well-known numbers showing how slow this is compared to any tracing GC, much less a good generational tracing GC like all non-Safari browsers have.)
The method lookup issue has massive consequences for optimization. Because JavaScript has a JIT, polymorphic inline caching is feasible, whereas in Objective-C it is not. It's been well known in Smalltalk research since the '80s that inline caching is essentially the only way to make dynamic method lookup acceptably fast. Moreover, JavaScript has the advantage of speculative optimization: when a particular method target has been observed, the JIT can perform speculative inlining and recompile the function. Inlining is key to all sorts of optimizations, because it converts intraprocedural optimizations to interprocedural optimizations. It can easily make 2x-10x of a difference or more in performance. This route is completely closed off to Objective-C (unless the programmer manually does imp caching or whatnot), because the compiler cannot see through method lookups.
Apple engineers know this, which is why Swift backed off to a more C++-like model for vtable dispatch and has aggressive devirtualization optimizations built on top of this model implemented in swiftc. This effort effectively makes iOS's native language catch up to what JavaScript JITs can already do through speculation.
Thanks for the detailed response, to summarize it sounds like your position is that:
1. Objective-C's compile time memory management is actually slower than JavaScript's garbage collection.
2. The performance consequences of Objective-C message sending are greater than JavaScript's JIT compilation. And furthermore, that JIT compilation is actually an advantage due to the other optimization techniques it enables.
I'd like to see a more direct comparison with benchmarks, but I can see where you're coming from.
Right. Note that this advantage pretty much goes away with Swift. Swift is very smartly designed to fix the exact problems that Apple was hitting with Objective-C performance.
I realized another issue, too: I don't think it's possible to perform scalar replacement of aggregates on Objective-C objects at all, whereas JavaScript engines are now starting to be able to escape analyze and SROA JS values. SROA is another critical optimization because it converts memory into SSA values, where instcombine and other optimizations can work on them. Again, Swift fixes this with SIL-level SROA.
I see, good point, but then I'd expect the cost of JIT compilation would still have a performance cost? As opposed to Objective-C being compiled before distribution to the client?
Here's a link showing Objective-C beating JavaScript handily: https://medium.com/@harrycheung/mobile-app-performance-redux...
But is this even a debate? Wouldn't you expect a compiled, manual memory managed, language to be faster than an interpreted language with garbage collection?