Friday, June 27, 2014

The Case for Message Passing in Swift

Michael Donald Buckley (via Ole Begemann):

Apple introduced Swift as “Objective-C without the C”, but in many ways, Swift is closer to “C++ without the C” (or Objective-C without the Smalltalk). Swift’s generics, for example, are closer to C++’s templates than to any feature of Objective-C. One of the more subtle ways that Swift resembles C++ is in how it calls methods. Unlike Objective-C, where methods are called using message passing, Swift uses a vtable for method dispatch, and when the compiler has enough information, inlines the function call directly. While this improves performance over message passing, it trades power and flexibility for performance gains that aren’t necessary for most apps.

In this article, I will present use cases which are currently impossible or difficult to implement without message passing.

[…]

Objective-C isn’t going away any time soon, but if Swift succeeds in becoming the dominant language for iOS and Mac development, Objective-C will go away. Eventually the cost of maintaining two languages and runtimes will cease to be worth it. Like Carbon before it, Objective-C will be deprecated, leaving Swift as the only supported language for app development on Apple platforms. In general, I am loathe to argue that my way is the one true way to do things, but since Swift will eventually be the one way to do things, and since now is the time when large changes will be easiest to introduce, I feel compelled to argue that Swift should forswear all but message passing.

[…]

On the Mac, swizzling is used to implement plug-in functionality, even for apps that don’t have a plug-in API. This adds features that are very important to power users. Many popular Photoshop and Xcode plug-ins use method swizzling. GPGMail, a plug-in for Mail.app which adds OpenPGP encryption to Mail.app, makes extensive use of method swizzling. This functionality is incredibly important to security-minded individuals, especially in the wake of the Snowden leaks. If Mail.app were rewritten in Swift, this would not be possible.

Drew Crawford:

Swift already does have a way to opt-in to message passing, it’s called the @objc flag (and performSelector:). It works fine, but it’s extra work to opt into it and use it. But, I don’t think that’s bad given that it disables so many useful optimizations.

What may be bad is that the name “@objc” is a dead giveaway that this is a feature with a deprecation date. So I think we need some other, reflectionish system going forward.

Michael Donald Buckley:

My argument is that Swift will be primarily used to write high-level apps. For these apps, message passing is almost never a bottleneck. Swift is not going to replace the optimized C and C++ code, especially for the really low-level stuff.

But even if Apple does decide to rewrite all the Core* frameworks et. al. with Swift, there’s still an argument that Swift should use message passing by default, and a way to opt in to vtable and direct dispatch for performance-critical code. For higher-level apps, message-passing is a lot less useful if it’s opt-in.

Marcel Weiher:

To me it looks like replacing ObjC and the frameworks (over time) and the style that puts everyone on an equal footing. So instead of having a language where anyone can build something like Core Data, you will have a language with built-in support for Core Data. Apple’s Core Data, that is, and you will like it. Just another tightening of the screws (App Store, App Store–only APIs despite promises).

Update (2014-07-05): Michael Donald Buckley (via Sash):

In the rare occsion that objc_msgSend is a bottleneck in an Objective-C app, there are techniques like IMP caching that can improve performance, and that’s really the kind of thing I’m advocating here. Give developers some way to opt in to vtables when there’s a real performance problem, but allow the greater flexibility of message sending by default. It’s possible to start with message passing and optimize when needed, but it’s not possible to start with vtable dispatch and use message sending when needed.

Message sending allows many problems to be solved with much less code. This increases programmer producivity and lowers maintenence costs. Since message sending is fast enough in most cases, the end user sees no difference between vtables and message sending, so Swift should use the solution that results in better programmer productivity.

14 Comments RSS · Twitter

Apple hasn't stopped supporting C and C++: what makes someone think they would stop supporting Objective-C? At least GNUStep would still be available, I suppose.

@Kevin To fully take advantage of Swift, they will at some point want native Swift APIs. That would make Objective-C a second-class citizen, even if it’s still supported.

I would not say that C/C++ are really supported today, in the sense that you need to use Objective-C APIs for many parts of the app.

Apple still supports C and C++, but they don't support Carbon anymore. To write something useful in C++, you either need to make a CLI program or a game of some sort, where you don't need the Cocoa APIs. If you want to write a normal Mac or iOS app, you have to use Objective-C, Objective-C++, or something like RubyMotion or Xamarin.

Objective-C++ is still important to some large powerhouse apps, namely Microsoft Office and Adobe Creative Suite. These apps are mostly written in C++, and send Objective-C calls on the Mac to render their GUIs.

When and if module support is completed for C++, and when and if Apple rewrites their GUI frameworks in Swift, then it will encourage those companies to replace their Objective-C code with Swift code, the same way they encouraged these companies to move from Carbon to Cocoa.

Farther in the future, the time may come when Apple stops supporting C and C++ compiler development, but if that happens, it doesn't mean the death of C++. There are enough other companies using C++ to make clang development continue to be worthwhile, and other commonly-used libraries like Boost and QT.

But Objective-C is not as loved as C++. When Apple drops support for Objective-C (which I bet is at least 10 years in the future), it might not even be worthwhile to continue to maintain support in clang. GNUStep is the only other platform really using it, but who knows what the state of GNUStep will be in 10 years? Even if GNUStep is a solid alternative, I'm going to use the tools, languages, and frameworks provided by the vendor, because I want to get my work done as quickly and easily as possible.

Interesting. I don't think swizzling is a sufficient justification for keeping message passing, particularly if its main use is hacking Apple apps.

On the other hand the inferior performance of Objective-C have forced the WebKit team to progressively move Obj-C code over to C/C++. Sure cross platform was a goal somewhat as well, but "number of platforms" was never on a WWDC slide.

I think Swift definitely has the potential of becoming a system programming language.

Carbon is an API, ObjC is a language. Don't compare apples to oranges...

I'd rather imagine that Apple keeps ObjC and Swift in parallel, mostly for different purposes - just like Managed C++ and C# in .NET

@Duncan I don’t think anyone is suggesting that swizzling is the only or even main justification. Michael’s post mentions some other uses for message passing. I also use it a lot with UI programming, e.g. to dispatch to per-action validation methods.

Your second point is what I was getting at in Wednesday’s post. I think Swift is tailor-made for something like WebKit.

This is a fair point, and I share the general sadness about the lack of dynamism in Swift. But, after all, Apple speakers at WWDC mentioned, that they want our input on Swift.
And, to be honest, people are already asking these questions: https://devforums.apple.com/message/992863 we just should be a bit more vocal about it:)

[…] well: instantiating classes by name, the ability to write your own Core Data–like framework, message passing (contra vtable dispatch), swizzling to work around bugs and add features, proxies/bridges, and […]

[…] code and older OS versions. It could still use the same runtime. With Swift, Apple is instead dropping some of the benefits of the Objective-C runtime and creating migration issues because some Swift […]

[…] is the sort of thing that really bothers me about Apple and Swift. I think Apple oversold how ready it was this […]

[…] and forth to Objective-C a lot, so they won’t see many benefits from pure Swift not doing message sending, and they may incur extra overhead due to bridging. Writing the code may be faster, […]

[…] a lot of dynamic behavior between -respondsToSelector: and dangerous swizzling, for example adding methods at runtime and […]

[…] because they are building on top of an imperfect platform. Since Swift’s introduction, I have been arguing that message passing (i.e. the dynamic keyword) should be the default, rather than […]

[…] The Case for Message Passing in Swift, “It’s a […]

Leave a Comment