Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Method Dispatch in Swift

Method Dispatch in Swift

A glimpse of my talk at SwiftBengaluru Meetup organised at WeWork, EGL, Bangalore.
The learning and take-aways are very simple and easy to engrain in our programming practices.

Avatar for Gaurav

Gaurav

May 19, 2018

Other Decks in Technology

Transcript

  1. “Method dispatch is the algorithm used to decide which method

    should be invoked in response to a message.” Keeping this definition here just as my respect towards people who have work done this before. You can ignore this complex definition.
  2. Execution Pipeline COMPILER LINKER LOADING RUNTIME - Static - Early

    Binding - Compile-time polymorphism - Compiler’s Favorite - Efficient - Cheaper* - Swift’s Forte - Dynamic - Late Binding - Run-time Polymorphism - Developers’ Favorite (at least it seems so) - Flexible - Little Expensive* to optimize - Powers Obj-C’s Method Swapping, and other sorcery compile-time run-time
  3. Binding is essentially anything (properties, functions) But dispatch is strictly

    about identifying method implementations The idea in dispatch is following some function pointer to see which method to actually invoke, or object to invoke it on. "Binding" is the idea that the method is "bound" to a particular instance (or class of instances) & that's how you identify it. Binding vs Dispatch
  4. Intro Method Dispatch is how a program selects which instructions

    to execute when invoking a method. It’s something that happens every time a method is called, and not something that you tend to think a lot about. - Static - Table - Message
  5. - Fastest style of method dispatch. - Result in the

    fewest number of assembly instructions. - The compiler can perform all sorts of smart tricks, like inlining code, inserting proper GOTOs, etc Static Dispatch
  6. - Uses array of function pointers for each method in

    the class declaration. - This array is generally referred to as virtual table, dispatch table or vtable - Swift uses the term witness table. Table Dispatch
  7. - Every subclass has its own copy of the table

    with a different function pointer for every method that the class has overridden. - As subclasses add new methods to the class, those methods are appended to the end of this array. Subclassing in Table dispatch
  8. Subclassing Table dispatch - Every subclass has its own copy

    of the table with a different function pointer for every method that the class has overridden. - As subclasses add new methods to the class, those methods are appended to the end of this array. class ParentClass { func method1() {} func method2() {} } class ChildClass: ParentClass { override func method2() {} func method3() {} }
  9. - Most dynamic method of invocation available. - Powers the

    techniques like KVO, UIAppearance. - Allows developers to modify the dispatch behavior at runtime (via swizzling) - Object contains a hidden pointer to it’s type. - Types in-turn contain a hidden pointer to their super types. Message Dispatch
  10. Subclassing in Message dispatch - When a message is dispatched,

    the runtime will crawl the class hierarchy to determine which method to invoke. - This is done using an “isa” pointer stored in every class and object - As These are just pointers, you can apply all sort of pointer arithmetic and perform runtime black-magic class ParentClass { func method1() {} func method2() {} } class ChildClass: ParentClass { override func method2() {} func method3() {} }
  11. What’s in for me? To write Performant Code We have

    just scratched the surface with these description. The motive was to bring everyone’s attention towards the concept. Let’s begin with ObjC vs Swift
  12. As we all know that Objective-C defers as much responsibilities

    as possible to the runtime. A very strong and extremely fast runtime complements this attitude. Objective-C - come what may!
  13. Swift takes a very calculated Approach (quite literally) towards optimization.

    Swift needs and try to perform as much as work at compile-time. This includes optimizing method dispatch. (Guess why your swift project compilation takes forever.) - Writing descriptive code with proper access-specifier gives the compiler enough information to make assumptions and optimizations (like Devirtualization optimization ) - If you don’t, compiler will still try to go out of its way to verify and optimize the code. Swift - Observe, Improvise, Overcome
  14. Candidates of improvement Method dispatch usually takes place in the

    realm of following constructs. - Classes - Structs - Enums - Protocol - Extensions (of all types) - Inheritance (Generics over weak-typing)
  15. Classes - Table Dispatch by default - Can be controlled

    by using suitable access specifiers or visibility control. - Use private, fileprivate, final appropriately to restrict the dynamic dispatch when not needed. Extension - Static Dispatch - One of the primary reason we cannot have stored properties in extensions. - Unlike classes/structs, the extension method will sport whatever access-specifier you defined for extension. - So all methods of a public extension will be public (and not internal unlike classes)
  16. Struct & Enums - Static Dispatch - Still use private,

    fileprivate, final appropriately to write beautiful and reasonable code Extension - Static Dispatch
  17. Protocols - Dynamic Dispatch Extension - Requirement Methods are dynamically

    Dispatched - Non-Requirement Methods are statically Dispatched - Resolved from the type of the caller.
  18. private, fileprivate and final - Static dispatch - Don’t hesitate

    to overuse it. dynamic - Makes it visible go Objc runtime AND - Forced to use ObjC Dynamic Table Dispatch - Use only when needed. - Eg: If you want to override methods in extensions. @objc - Makes it visible go Objc runtime - No Effect on dispatch - Don’t hesitate to overuse it. @nonobjc - Makes a Swift declaration unavailable in Objective-C - Enforces Swift Visibility and Access specifiers
  19. Problems with Generics. - UIKit doesn’t really go well with

    generics. - Interface builder is generics-illitrates - Enter Generics - Generics are resolved at compile-time - Type Safe + predictable code = Happy Compiler Inheritance
  20. Analyze Build time Want to know how much time the

    build is taking on a method level? You can use this Swift flag to find out which methods are taking more time to compile. Under Target > Build Settings > Other Swift Flags -Xfrontend -debug-time-function-bodies Mac App If you are a visual person, you can install the Swift build time Analyzer Mac app that helps you visualize this data. Bonus
  21. Why pay for a car if you can subscribe and

    earn ? https://www.zoomcar.com/zap/subscribe
  22. Why pay for a dynamic Behaviour when you don’t need

    it? Apple: Increasing Performance by Reducing Dynamic Dispatch
  23. Method Dispatch / other optimizations happen under the hood and

    are completely abstracted by us. But we can surely take charge and control that with minimal efforts and practice. Don’t pay (in compile time and runtime ) for the dynamism that you don’t even need. Conclusion