piątek, 11 grudnia 2015

Things you need to know about Swift's runtime

When learning advanced features of Objective-C I learned how much power does knowing about it's runtime give you. I've decided to start my adventure with Swift with studying it's runtime. This way you know exactly what you're telling the computer to do. 

Class vs Struct

Ahh, the famous "class vs struct" Google search. 

Październik 2014 - October 2014 - Release of Swift

Of course, structs are less complicated, thread safe and helpful when designing immutable models. What we're interested in this post though, is the runtime. 

A lot of people will say "structs are safe, but slow, because their value has to be copied every time it's passed", and won't even imagine how wrong they are.

Structs are way faster to allocate and deallocate, because they're values, so they're stored on the stack. Operations on the stack are much faster, than complicated operations on the heap. Here's some dedicated guy that actually tested it (swift 1.2, though).

Ok, but copying structs is an operation that you're going to do often - obviously it has to be slower than just copying references ? It also should take much more memory than simple references? It doesn't have to be true. Here's what apple has to say about it:

"... “copying” of strings, arrays, and dictionaries. The behavior you see in your code will always be as if a copy took place. However, Swift only performs an actual copy behind the scenes when it is absolutely necessary to do so. Swift manages all value copying to ensure optimal performance, and you should not avoid assignment to try to preempt this optimization."

That means that when you copy structs, it doesn't have to mean that the memory copy will be executed and doubled. Swift uses copy-on-write, that makes sure that the memory will be copied only when changed.

Let vs Var

Of course you know the difference by now, but did you know that setting your variables as constants can affect the performance of your program ? Setting your variables as let tells the compiler that it can apply the value as inline in code. This means that it doesn't involve allocating any memory.

It's something that's been with us since C, but it's worth mentioning that it works the same with class, inline and instance methods. Inline, and class methods are much faster. For the same reason as above.

Is Swift dynamic or static ?

The best part for last. Swift's class methods are sometimes resolved dynamically, and sometimes statically. What this means is that the compiler knows exactly which method to call, and sometimes runtime has to lookup a vtable to find the correct method. Try to make sure that it's always static by:

Using final and private keywords - the compiler will know that the methods won't be overriden, so it can statically assign the method, otherwise it'll use a virtual table lookup to resolve.

Avoiding subclassing NSObject - this will make the class use Objective-C dynamic dispatch

• Avoid using @dynamic keyword - same

One good thing about having dynamic dispatch is method swizzling.

It's funny that good performance in Swift = clean code :)

Want to know more ? Swift has been open sourced so it's an open book now :)