Does Swift use message dispatch for methods? - swift

I'm sure my terminology is off, so here's an example:
C/C++ has methods and virtual methods. Both have the opportunity to be inlined at compile time.
C#'s CIL has call and callvirt instructions (which closely resemble C++ methods and virtual methods). Although almost all method calls in C# become callvirt (due to langauge snafu) the JIT compiler is able to optimize most back to call instructions and then (if worthwhile) also inline them.
Objective-C method calls are done very differently (and inefficiently); a message object is passed via objc_msgsend every time you call a method, it's a form of dynamic dispatch, and can never be inlined.
Reading up on the language specification for functions for Swift, I don't know if Swift is using the same messaging system as Objective-C or something different.

Sometimes yes, sometimes no. If you have pure swift code, and do not expose your classes/protocols to Objective-C with the #objc decoration, it appears that pure-swift method calls are not dispatched via objc_msgSend, however in other cases they are. If the protocol your swift object adopts is declared in Objective-C, or if the swift protocol is decorated with #objc, then method calls to protocol methods, even from swift objects to other swift objects, are dispatched via objc_msgSend.
The documentation is currently a little thin; I'm sure there are other nuances... but empirically speaking (i.e. I've tried it out) some swift method calls go through objc_msgSend and others don't. I think getting the best performance will be dependent on keeping your code as much pure-swift as possible and crossing the Obj-C/swift boundary as little as possible, and through bottleneck interfaces/protocols, so as to limit the number of swift calls that have to be dispatched dynamically.
I'm sure more detailed docs will emerge sooner or later.

Unlike C++, it is not necessary to designate that a method is virtual in Swift. The compiler will work out which of the following to use:
The performance metrics of course depend on hardware.
Inline the method : 0 ns
Static dispatch: < 1.1ns
Virtual dispatch 1.1ns (like Java, C# or C++ when designated).
Dynamic Dispatch 4.9ns (like Objective-C).
Objective-C of course always uses the latter. The 4.9ns overhead is not usually a problem as this would represent a small fraction of the overall method execution time. However, where necessary developers could seamlessly fall-back to C or C++ where required. This is still somewhat of an option in Swift, however the compiler will analyze which of the fastest can be used and try to decide on your behalf.
One side-effect of this, is that some of the powerful features afforded by dynamic dispatch may not be available, where as this could previously have been assumed to be the case for any Objective-C method. Dynamic dispatch is used for method interception, which is in turn used by:
Cocoa-style property observers.
CoreData model object instrumentation.
Aspect Oriented Programming
With the latest release of Swift, even if an Object is marked as '#objc' or extends NSObject the compiler may still not necessarily use dynamic dispatch. There's a dynamic attribute that can be added to the method to opt-in.

Related

Swift Compile Times - Should the `final` keyword increase or decrease compile time? [duplicate]

Except for obvious reasons, such as if by design I do not want certain method, or property, or whatever to be overridden down the inheritance tree, are there other reasons to mark things final in Swift?
For example, are there performance considerations? I recall reading somewhere on SO answers that suggest something along the line.
From Apple's Swift blog: Increasing Performance by Reducing Dynamic Dispatch
Swift allows a class to override methods and properties declared in its superclasses. This means that the program has to determine at runtime which method or property is being referred to and then perform an indirect call or indirect access. This technique, called dynamic dispatch, increases language expressivity at the cost of a constant amount of runtime overhead for each indirect usage.
Using final is one of several ways to improve performance by eliminating such dynamism:
The "final" keyword is a restriction on a class, method, or property that indicates that the declaration cannot be overridden. This allows the compiler to safely elide dynamic dispatch indirection.

Why mark something final in Swift except for architectural considerations?

Except for obvious reasons, such as if by design I do not want certain method, or property, or whatever to be overridden down the inheritance tree, are there other reasons to mark things final in Swift?
For example, are there performance considerations? I recall reading somewhere on SO answers that suggest something along the line.
From Apple's Swift blog: Increasing Performance by Reducing Dynamic Dispatch
Swift allows a class to override methods and properties declared in its superclasses. This means that the program has to determine at runtime which method or property is being referred to and then perform an indirect call or indirect access. This technique, called dynamic dispatch, increases language expressivity at the cost of a constant amount of runtime overhead for each indirect usage.
Using final is one of several ways to improve performance by eliminating such dynamism:
The "final" keyword is a restriction on a class, method, or property that indicates that the declaration cannot be overridden. This allows the compiler to safely elide dynamic dispatch indirection.

Swift language statically or dynamically dispatched?

Reading Swift language guide I cannot find explicit information whether Swift is statically dispatched (like basic C++, Java, C#) or dynamically dispatched (like Objective-C).
The documentation of language features (like classes, extensions, generics, etc) seems to suggest that it is statically typed, which might be the source of supposed speed improvements. However, Apple stated on the WWDC 2014 keynote that the language uses the same runtime as Objective-C, and is very compatible with Cocoa/Cocoa Touch, which suggest dynamic dispatch.
Describing C++, Java, and C# as statically dispatched is not particularly accurate. All three languages can and often do use dynamic dispatch.
Swift, similarly, can do both. It does differ from ObjC in that it does not always dynamically dispatch. Methods marked #final can be statically dispatched, as can struct and enum methods. I believe non-final methods can be statically dispatched if the runtime type can be proven at compile time (similar to C++ devirtualization), but I'm not certain about the details there.
According to this excerpt from Y Combinator (https://news.ycombinator.com/item?id=7835099):
From a user's point of view, it's basically straight out of the Rust book, all the gravy with also relaxed ownership and syntax.
It has it all [1]: static typing, type inference, explicit mutability, closures, pattern matching, optionals (with own syntax!
also "any"), generics, interfaces, weak ownership, tuples, plus other
nifty things like shorthand syntax, final and explicit override...
It screams "modern!", has all the latest circlejerk features. It even comes with a light-table/bret-victor style playground. But is
still a practical language which looks approachable and
straightforward.
Edit: [1]: well, almost. I don't think I've caught anything about generators, first-class concurrency and parallelism, or tail-call optimization, among others.

Tracing Allocations Test Results - look good or not so good?

I'm trying to memory test my app.
I've followed the Organizer - Documentation article entitled "Recovering Memory You Have Abandoned", but I'm not sure if the results make my tested page good or bad, or somewhere in-between.
(My test involved: navigate to page 2, going back to page 1, press 'Mark Heap' -repeated 25 times for good measure.)
Attached is a screenshot of my allocations test. Most of the #Persistent values are 0. But there are some anomalies. Are these typical?
(The last Heapshot, 26, was taken after stopping the recording, and pressing 'Mark Heap' at the end of the trace - as suggested in the documentation.)
I would be very grateful for some advice. Thanks.
I believe that you are using ARC, and if you are using ARC, there is no need of bothering about the heaps, it will take care of everything.
Here are the 9 simple points from Apple's docs to be in mind while using ARC:
ARC imposes some new rules that are not present when using other
compiler modes. The rules are intended to provide a fully reliable
memory management model; in some cases, they simply enforce best
practice, in some others they simplify your code or are obvious
corollaries of your not having to deal with memory management. If you
violate these rules, you get an immediate compile-time error, not a
subtle bug that may become apparent at runtime.
You cannot explicitly invoke dealloc, or implement or invoke retain,
release, retainCount, or autorelease.
The prohibition extends to using #selector(retain), #selector(release), and so on.
You may implement a dealloc method if you need to manage resources other than releasing instance variables. You do not have to
(indeed you cannot) release instance variables, but you may need to
invoke [systemClassInstance setDelegate:nil] on system classes and
other code that isn’t compiled using ARC.
Custom dealloc methods in ARC do not require a call to [super dealloc] (it actually results in a compiler error). The
chaining to
super is automated and enforced by the compiler.
You can still use CFRetain, CFRelease, and other related functions
with Core Foundation-style
You cannot use NSAllocateObject or NSDeallocateObject.
You create objects using alloc; the runtime takes care of
deallocating objects.
You cannot use object pointers in C structures.
Rather than using a struct, you can create an Objective-C class to manage the data instead.
There is no casual casting between id and void *.
You must use special casts that tell the compiler about object lifetime. You need to do this to cast between Objective-C objects and
Core Foundation types that you pass as function arguments. For more
details, see “Managing Toll-Free Bridging.”
You cannot use NSAutoreleasePool objects.
ARC provides #autoreleasepool blocks instead. These have an advantage of being more efficient than NSAutoreleasePool.
You cannot use memory zones.
There is no need to use NSZone any more—they are ignored by the modern Objective-C runtime anyway.

In GWT, why shouldn't a method return an interface?

In this video from Google IO 2009, the presenter very quickly says that signatures of methods should return concrete types instead of interfaces.
From what I heard in the video, this has something to do with the GWT Java-to-Javascript compiler.
What's the reason behind this choice ?
What does the interface in the method signature do to the compiler ?
What methods can return interfaces instead of concrete types, and which are better off returning concrete instances ?
This has to do with the gwt-compiler, as you say correctly. EDIT: However, as Daniel noted in a comment below, this does not apply to the gwt-compiler in general but only when using GWT-RPC.
If you declare List instead of ArrayList as the return type, the gwt-compiler will include the complete List-hierarchy (i.e. all types implementing List) in your compiled code. If you use ArrayList, the compiler will only need to include the ArrayList hierarchy (i.e. all types implementing ArrayList -- which usually is just ArrayList itself). Using an interface instead of a concrete class you will pay a penalty in terms of compile time and in the size of your generated code (and thus the amount of code each user has to download when running your app).
You were also asking for the reason: If you use the interface (instead of a concrete class) the compiler does not know at compile time which implementations of these interfaces are going to be used. Thus, it includes all possible implementations.
Regarding your last question: all methods CAN be declared to return interface (that is what you ment, right?). However, the above penalty applies.
And by the way: As I understand it, this problem is not restricted to methods. It applies to all type declarations: variables, parameters. Whenever you use an interface to declare something, the compiler will include the complete hierarchy of sub-interfaces and implementing classes. (So obviously if you declare your own interface with only one or two implementing classes then you are not incurring a big penalty. That is how I use interfaces in GWT.)
In short: use concrete classes whenever possible.
(Small suggestion: it would help if you gave the time stamp when you refer to a video.)
This and other performance tips were presented at Google IO 2011 - High-performance GWT.
At about the 7 min point the speak addresses 'RPC Type Explosion':
For some reason I thought the GWT compiler would optimize it away again but it appears I was mistaken.