[swift-evolution] [Pitch] Changing NSObject dispatch behavior
rodney.brown6 at icloud.com
Thu Dec 29 22:00:34 CST 2016
> On 30 Dec 2016, at 10:50 am, Freak Show <freakshow42 at mac.com> wrote:
>> On Dec 29, 2016, at 13:28, Rod Brown via swift-evolution <swift-evolution at swift.org> wrote:
>> I’m in agreement that ‘dynamic’ is probably not what you want without a declaration.
> I hold a completely opposite viewpoint. Dynamic is always what I want and table based is premature optimization. Late binding is important. I found far too often when working in C++ (yes I am really flipping old) I would come across code where a developer hadn't chosen to make a method virtual and I found myself just up a creek with regards to extending that code. Ditto people declaring stuff final in Java for no good reason.
> The important thing to consider is that the future is generally unknowable and if you don't know the future you cannot make good choices about what should and should not be dynamic. So the conservative thing is to make everything dynamic until you cannot afford it - which...is usually never.
Then that’s great. If you’d prefer to work with a more open, overridable and intercetable platform which is dynamic by default, Apple has your back: Obj-C. It’s not deprecated. It’s actually the language they’re still writing iOS, OS X, tvOS and watchOS higher level frameworks in still, so you’re covered. Who is forcing you to use Swift, a language where compiler optimisations like this a stated goal?
>> The only difference between table and method dispatch is the Objective-C message dispatch system. Unless users want to work around things by manually handling with some of the complex machinery in Obj-C, which is rare, then there is no reason behind doing so, and all it comes down to is a relatively large performance hit for nothing. And to be honest, with very few exceptions, if you’re using that ultra-dynamic machinery, you’re probably Doing It Wrong in the first place.
> I do this sort of thing routinely and I assure you I am not Doing It Wrong.
Ok, so you do it a lot. That means definitively it’s the best way?
Obj-C was designed to constantly be interfering with method dispatch? You can do it, it’s there, message forwarding, those types of mechanisms, but if you’re relying on that for your day-to-day work, you’re in for a load of trouble, and you’re hacking around frameworks using the language rather than working with the frameworks. Apple don’t design their frameworks first and foremost for us to get in there and start using method swizzling or the like - in fact they specifically discourage it. Just because you do it and you think you’re smart doesn’t make it good design.
There are rare instances where frameworks and implementations use some of the really dynamic stuff, like CoreData, or KVO. That’s great. I’m not arguing there isn’t a use for it. I’m saying you pay a massive hit, 90% of the time for no reason.
> I don't get why there is so much emphasis on performance in this day and age. I haven't run into a performance problem I could trace to speed of ObjectiveC's method dispatching since the early 90’s.
Do a time profile of a modern Obj-C application. You’ll find that 15% of the time the application is running, it’s stuck in the middle of objc_msgSend. That’s a massive overhead in anyone’s books. Why is this important?
1. More CPU use equals more battery drain. Considering the vast majority of Apple’s platforms and the direction of computing as a whole is dependent on batteries rather than plugs in walls, this is important.
2. Moore’s Law won’t continue. We’re getting to the end of the road in what CPU advances have given us, and all those core multiplications just ends in more locks - we need to be more efficient because in 40 years of computing, we haven’t worried about making our software better, we just waited for CPU’s to catch up. News Flash: They won’t. Time for us to stop justifying ourselves and do something about making ourselves better at using the processing power we have.
3. Swift wasn’t designed just to replace Obj-C, a relatively high level language. It was designed to scale from system programming to the higher levels as well. Obj-C is good for basic UI development because you rarely tax the limits and are rarely worried about getting performance out of it.
4. Because performance in the language and its frameworks benefits everyone by giving more flexibility to their users.
> Second - I have quite a lot of code that relies on this sort of dynamism. I've been a very serious C++ developer and a very serious Smalltalk programmer at various times in my career and I value the flexibility of late binding far above performance.
>> If you need this functionality, dynamic still exists. But Swift is Table Dispatch by default for a reason: you’re paying a massive penalty for something you’ll rarely if ever use, and it should be opt in.
> Strongly disagree.
>>> On 15 Dec 2016, at 10:15 am, Brian King via swift-evolution <swift-evolution at swift.org> wrote:
>>> I wanted to follow up to a blog post I wrote about Message Dispatch in
>>> Swift — https://www.raizlabs.com/dev/2016/12/swift-method-dispatch. I
>>> mentioned some changes to NSObject that didn’t result in any
>>> objections, so I thought it was time to see what the SE mailing list
>>> I’ve read a few conversations on SE mailing list that have morphed
>>> into abstract conversations about dynamic vs static dispatch. I want
>>> to focus specifically on how Swift NSObject subclasses behave.
>>> I think that there are 2 changes that will result in fewer bugs and
>>> will not have a substantial impact on performance:
>>> ## Remove Table Dispatch from NSObject
>>> NSObject subclasses use table dispatch for the initial class
>>> declaration block. I think that using message dispatch for NSObject
>>> subclasses everywhere will result in a much more consistent developer
>>> ## Block NSObject Visibility Optimizations
>>> Swift upgrades method dispatch to final when the compiler can prove
>>> that the method is not subclassed. I would like to see Swift be more
>>> careful about the impact of these optimizations on message dispatch,
>>> and consider message dispatch non-upgradable.
>>> I thought it would help to frame this choice as a trade-off between
>>> Swift’s goals of safe, fast, and expressive.
>>> ## Safe
>>> Always using message dispatch for NSObject subclasses will fix a class
>>> of runtime errors in framework features that are designed around
>>> message passing (e.g. KVO). Arguments against using dynamic features
>>> like this are valid, but Cocoa frameworks still use dynamic features
>>> and the above behaviors result in actual bugs. As a bonus, this will
>>> resolve SR-584, where a table-dispatched method that is overridden by
>>> a message dispatch method doesn’t behave correctly.
>>> ## Fast
>>> The above changes will result in slower dispatch in NSObject
>>> subclasses. However, I don't think that these dispatch changes
>>> actually have a tangible impact on performance. Most NSObject
>>> subclasses sit on top of a lot of `objc_msgSend`, and if there is a
>>> specific hot spot, it would still be optimizable via the final
>>> ## Expressive
>>> Using table dispatch for NSObject without any source indication or
>>> library documentation is not very expressive. I think it’s important
>>> to weigh table dispatch behavior against all of the framework
>>> documentation and developer experience that assume message dispatch.
>>> This will also eliminate the need for a lot of `@objc` and `dynamic`
>>> annotations that are often inconsistently applied depending on if they
>>> are needed in the scope they are defined in (e.g. class vs extension).
>>> If this idea shows promise, I’d be glad to formalize a Swift Evolution
>>> Proposal and explore syntactic details. I think being able to flag a
>>> class with `dynamic` and applying this flag to `NSObject` may be the
>>> only syntactic change needed. However, it would be good to debate the
>>> merit of the behavior change before the syntax.
>>> Brian King
>>> swift-evolution mailing list
>>> swift-evolution at swift.org
>> swift-evolution mailing list
>> swift-evolution at swift.org
More information about the swift-evolution