Infinum iOS Talks #1 - Swift under the hood: Method Dispatching by Vlaho Poluta

31
Swift under the hood: Method Dispatching VLAHO POLUTA

Transcript of Infinum iOS Talks #1 - Swift under the hood: Method Dispatching by Vlaho Poluta

Swift under the hood: Method Dispatching

VLAHO POLUTA

01METHOD DISPATCHING

Method dispatch is the algorithm used to decide which method should be invoked in

response to a message.

[RECEIVER MESSAGE] objc_msgSend(receiver, selector)

STATIC DISPATCH Decided at Compile-time

DYNAMIC DISPATCH Decided at Run-time

02 C++

STATIC DISPATCH class AnimalStatic { public: void eat() { std::out << “I’m eating food.”; } }

DYNAMIC DISPATCH class AnimalVirtual { public: virtual void eat() { std::out << “I’m eating generic food.”; } }

VTABLE IN C

typedef struct { PTRFUN* vTablePtr; const char *x; const char *y; } Animal;

receiver→vTable[2]()

03 OBJECTIVE C

objc_msgSend(receiver, selector)

struct objc_class { struct objc_class *isa; struct objc_class *super_class; const char *name; long version; long info; long instance_size; struct objc_ivar_list *ivars;

struct objc_method_list **methodLists;

struct objc_cache *cache; struct objc_protocol_list *protocols; };

typedef struct objc_method *Method;

struct objc_method { SEL method_name; char *method_types; IMP method_imp; };

typedef struct objc_cache * Cache;

#define CACHE_BUCKET_NAME(B) ((B)->method_name) #define CACHE_BUCKET_IMP(B) ((B)->method_imp) #define CACHE_BUCKET_VALID(B) (B) #define CACHE_HASH(sel, mask) (((uarith_t)(sel)>>2) & (mask)) struct objc_cache { unsigned int mask; /* total = mask + 1 */ unsigned int occupied; Method buckets[1]; };

04SWIFT

STATIC DISPATCH

class AnimalStatic { final func eat() { print("I’m eating food.") } }

final class AnimalStatic { func eat() {

print("I’m eating food.") } }

Swift can generate Obj-C classes and use runtime

Swift classes are Obj-C classes

NEW ROOT CLASS SwiftObject

Conforms to the NSObjectProtocol

methodLists vTable

05WHEN IN DOUBT, CMD+R!

class AddNameHereClass { func addSubOne(num: Int) -> Int {/*…*/} }

let addNameClass = AddNameHereClass()

TEST

let startTime = NSDate()

addNameClass.addSubOne(test) x50000 times

print( NSDate().timeIntervalSinceDate(startTime))

@objc class ObjcClass: NSObject { func addSubOne(num: Int) -> Int {/*…*/} }

let objcClass = ObjcClass()

0.0056279…

@objc class ObjcClass: NSObject { func addSubOne(num: Int) -> Int {/*…*/} }

let objcClass = ObjcClass()

0.0056279…

class SwiftClass { func addSubOne(num: Int) -> Int {/*…*/}

}

let swiftClass = SwiftClass()

0.0014960…

@objc class ObjcClass: NSObject { func addSubOne(num: Int) -> Int {/*…*/} }

let objcClass = ObjcClass()

0.0056279…

class SwiftClass { func addSubOne(num: Int) -> Int {/*…*/}

}

let swiftClass = SwiftClass()

0.0014960…

class FinalClass { final func addSubOne(num: Int) -> Int {/*…*/} }

let finalClass = FinalClass()

0.0013079…

@objc class ObjcClass: NSObject { func addSubOne(num: Int) -> Int {/*…*/} }

let objcClass = ObjcClass()

0.0056279…

class SwiftClass { func addSubOne(num: Int) -> Int {/*…*/}

}

let swiftClass = SwiftClass()

0.0014960…

class FinalClass { final func addSubOne(num: Int) -> Int {/*…*/} }

let finalClass = FinalClass()

0.0013079…

06CONCLUSION

SWIFT As fast or faster than Obj-C