Stuff implemented in java and javascript, not so much.
Maybe saying objc is cheating a little bit, because it's so easy to drop into straight C to optimize. But stuff like UITableView (edit: scroll => table) is all heavily based on objc message sending, and it's easy to get great scrolling perf using that api.
I don't know the exact number, but you can get a lot of message sends done in 16ms.
(Another example -- GitUp, insanely fast git client, objc.)
(On the other hand, I do remember that C++ based BeOS on 66 MHz PowerPCs back in the day was double-insanely fast, so maybe Obj-C is slow, on a language level, and we just don't know it because everything else is so much slower, on an implementation level. But then again that stuff was all virtual calls. I just don't buy the argument that at the _system framework_ level dynamic dispatch is a barrier to good performance.)
> Stuff implemented in java and javascript, not so much.
I agree with the data but not the conclusion. iOS' performance is great in spite of using Objective-C as its language, not because of it.
The only performance-related features that Objective-C brings to the table are (a) being able to piggyback on the optimizations implemented in popular open source C++ compilers; (b) being compatible with C, so you can easily inline C into Objective-C when Objective-C's slow performance bites you; (c) not requiring tracing garbage collection. When you're actually in heavy Objective-C land with method calls in tight loops, performance is pretty bad, both because message sending is slow and because methods can't be devirtualized. Apple knows this, and they've basically reached the limit of what they can do without incompatible changes to the Objective-C semantics. Hence the performance-related design decisions in Swift.
(As for UIScrollView/UITableView, I agree that they're very fast relative to Android or current Web browsers for example. I know the reasons for this and they have nothing to do with the implementation language. Algorithmic and engineering concerns often trump programming language performance.)
I agree with you on the specifics, but somehow still reach different conclusions. :)
Edit: I guess if you take the lense of wanting Swift to replace the combination of ObjC + plain C, what you're saying makes sense.
It's a shame though if you end up losing the very-helpful ability to dynamically modify system provided behavior.
And even for relatively performance intensive stuff, like table scrolling, objc is plenty fast.
Every language obviously has its domain of performance-appropriateness -- C too will hit its limits; x264 w/o the asm optimizations is ungodly slow, for example.
I just think for "apps", generally, objc is a speedy language. Empirically this is true. Explanations that call for this being true "despite the language" are suspicious to me; if it's not the language, what's the magic pixie dust?
And personally I suspect the swift folks aren't going the more static route because of actual real-world user-facing performance walls they've run into, but because that's what they're into -- they're C++/static language/compiler guys.
Last example: Look at the most performance constrained stuff apple is currently doing, the watch. Think that's Swift? I'm pretty sure it's not.
Nope. Objective-C is a great language for performance. Remember the 97-3 rule. That is, only roughly 3% of your code are responsible for almost all the performance. You just don't know which parts those are.
The dynamic features of the language give you awesome productivity to more quickly get to the point where you find out which 3% to actually optimize heavily. Doing this optimization is straightforward because you have all the tools at your disposal, the road to them is smooth and the performance model is predictable.
I have repeatedly achieved performance that's better (yes!) than equivalent C programs, and with a little bit of work you can actually maintain nice OO APIs.
>(b) being compatible with C so you can easily inline C into Objective-C
I really don't understand where this (common) misunderstanding is coming from. Objective-C is C, or more precisely a superset of C. You don't "inline C into Objective-C". You use different aspects of Objective-C as appropriate. If you are not capable of using the full capabilities of the languages, that is your fault, not a problem of Objective-C.
This seems to have been lost, with people (inappropriately) using Objective-C as a pure object-oriented language. It is not. It is a hybrid object-oriented language. In fact, the way it was intended to be used is to write your components using C and use dynamic messaging as flexible packaging or glue.
> because methods can't be devirtualized
Sure they can. I do it all the time:
SEL msgSel=@selector(someMessage:);
IMP devirtualized = [object methodForSelector: msgSel];
for (i=0;i<LARGE_NUMBER;i++) {
devirtualized( object, msgSel, arg[i] );
}
Did you mean they can't be automatically devirtualized by the compiler? I hope you understand that these are two different things. Of course, it would be nice to have compiler support for this sort of thing, which would have been miles easier than coming up with a whole new language: for (i=0;i<LARGE_NUMBER;i++) {
[[object cached:&cache] someMessage:arg[i]];
}
Or some other mechanism using const.> reached the limit of what they can do without incompatible changes to the Objective-C semantics. > Hence the performance-related design decisions in Swift.
Swift performance is significantly worse and waaaayy less predictable than Objective-C, and that is despite the Swift compiler running a bunch of mandatory optimizations even at -O0.
A function pointer that's in a local variable, so loaded into a register is a completely different beast, as the measurements bear out.
In my measurements, a message-send is ~40% slower than a C++ virtual method call, whereas an IMP-cached function call is ~40% faster, and slightly faster than a regular function call.
Finding calling via a function pointer to be faster than calling directly suggests that you were not actually measuring what you thought you were measuring.
I'd be curious to hear more about the reasons. I'm not familiar with the web side, but Android layout performance can be painful, especially on older devices running Dalvik.
In addition, message-sending is extremely cheap compared to other operations, for example roughly 50x faster than object allocation.
Last not least, in the few cases where messaging does become an issue, it is trivial to replace with more optimized dispatch, ranging from an IMP-cached send to a static inline function depending on the performance requirements and API boundaries in question.
Swift currently can't hold a candle to Objective-C on the performance front, which is why all the heavy lifting is done in Objective-C. As a small example, see how many articles there are on "Swift JSON parsing", then check what percentage of those call into the NSJSONSerialization Objective-C class to the actual, you know, parsing.
[1] https://www.mikeash.com/pyblog/performance-comparisons-of-co...
But it's even worse than that: I'm talking about devirtualized calls, which are far faster than virtual calls in C++. More importantly than just the call time, devirtualization can have outsized performance impact because it enables inlining, converting intraprocedural optimizations to interprocedural optimizations. The difference between inlining and not can easily be a 10x-level performance difference with an optimizing compiler like LLVM.
If you want inlining, use a static inline function.