
The Objective-C Runtime and Swift Dynamism - mrkd
https://academy.realm.io/posts/mobilization-roy-marmelstein-objective-c-runtime-swift-dynamic/
======
thewayfarer
This is particularly relevant right now. The swift-evolution mailing list is
currently discussing adding a "dynamic member lookup" protocol to Swift to
enhance interop with dynamic languages like Python, Ruby, and Perl. You can
see the proposal here[0].

[0]
[https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae...](https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438)

------
dep_b
I still like Objective-C even if it isn't my go-to language anymore. It's
quite elegant compared to it's peers from the 80's, it's a very small language
yet you can achieve everything with it, even if it means dipping into C(++)
for the parts that need to be really performant. But on the other hand seeing
a different programming language when there's some optimization going on and
having another programming language for business logic is a great thing too.

How many times don't we see bugs, errors or security issues stemming from the
fact that business logic gets implemented in C?

~~~
nerdponx
What is cross-platform development like?

Also, what about Objective-C prevents business logic bugs?

~~~
dep_b
> What is cross-platform development like?

Sorry, never tried that.

> Also, what about Objective-C prevents business logic bugs?

Generically speaking C makes it easy to interact with the computer memory but
harder to abstract things while OO languages have it reverse.

C has GOTO, Objective-C not.

Objective-C has objects that easily can encapsulate different aspects of your
logic. Objective-C is very verbose and readable while most C API's aren't.

Obviously Swift is even better in that regard as it has better types and
checks but it doesn't allow you to seamlessly use C.

------
btreesOfSpring
I'm getting the loading error, "An error occurred in the application and your
page could not be served. If you are the application owner, check your logs
for details."

Not sure if there is a mirror, a write-up, or another example anyone might be
able to pass along.

edit: this google cache version is working[0].

[0]
[https://webcache.googleusercontent.com/search?q=cache:gXiqzW...](https://webcache.googleusercontent.com/search?q=cache:gXiqzW0OV04J:https://academy.realm.io/posts/mobilization-
roy-marmelstein-objective-c-runtime-swift-
dynamic+&cd=1&hl=en&ct=clnk&gl=us&lr=lang_de%7Clang_en)

~~~
tambourine_man
You can watch the talk with google cache. It’s from 2016.

Basically, Swift dynamism is coming, hopefully safer than ObjC

------
skue
_> Before we start, Objective-C is a runtime-oriented language, which means
that all of the links between your methods and variables and classes are
deferred to the last moment possible to when your app is actually running, and
this gives you great flexibility because you can change those links. The
alternative, where Swift is most of the time, is compiletime-oriented
languages. So in Swift everything is a bit more harder bound, and you get more
safety, but it’s less flexible._

 _> This is what this debate was all about._

Not just _safety_ , but also performance. Swift offers significant performance
gains when you don’t need the dynamism. Swift lets you opt into dynamic
features (as he later explains), and you can seemlessly interact with
Objective C on Mac platforms. But you don’t have to pay the penalty for
dynamism in the vast majority of your code that doesn’t use these features.

Edited: I also pointed out some additional mistakes in the post, but removed
that because this comment got too long.

~~~
mpweiher
> Not just safety, but also performance. Swift offers significant performance
> gains

This is a common misconception. It is not true. Swift is slower than
Objective-C, typically significantly so.

~~~
skue
When arguing against a “common misconception,” one typically provides a
source.

You seem to be saying that Apple’s claims are not only wrong, but ObjC is
somehow faster despite having to do more work. Swift has no runtime method
table lookups, no extra objc_msgSend calls, better ability to analyze and
inline code, no retain/release dance for code with value semantics, etc. Every
benchmark I’ve seen shows Swift faster for these reasons.

~~~
panic
Do you have experience writing Swift or Obj-C programs? My experience is that
Obj-C has predictable performance which is often "good enough", whereas Swift
is either too slow (without optimizations) or takes a very long time to
compile (with optimizations enabled).

As a concrete example, I took a Swift program I had lying around (8 files,
2854 lines total), compiled it without optimizations, and stress-tested it a
bit. Here's what the "bottom-up" profile looks like:
[https://i.imgur.com/ohlKQgx.png](https://i.imgur.com/ohlKQgx.png) \-- tons of
time wasted in Swift runtime overhead. Compiling with optimizations removes
most of the overhead, but a clean build of this (relatively small) program
took almost 5 minutes with optimizations enabled.

~~~
i2om3r
Did you compare it to a roughly equivalent Objective-C program? The top four
entries in your profile data show retain, release and objc_msgSend. You will
have those in Objective-C too. Maybe to a different degree? That's also why I
am asking whether you have similar Objective-C code to test. Or maybe it's
just that unoptimized Swift code is slower and optimized code is faster?

Compile times are a related but different matter. There are -warn-long-
function-bodies and recently -warn-long-expression-type-checking which are
really helpful and can give you an idea where most of the compile time is
spent. In my experience, the type checker can spend a _lot_ of time in mildly
complex expressions involving overload resolution, which can be really
annoying but there are often ways around it. With those culprits being
eliminated, I have never encountered 5 minute build times for projects of this
size or bigger, and I like to imagine that I write fairly generic code.

~~~
panic
Thanks, I didn't know about those flags! I suspect there was a pathological
expression somewhere, since most of that time was spent in a single file.

------
bogomipz
>"Before we start, Objective-C is a runtime-oriented language, which means
that all of the links between your methods and variables and classes are
deferred to the last moment possible to when your app is actually running,
..."

I had not heard the term "runtime-oriented language" before. Is this really
just another term for "supports reflection"? If not what would be other
examples of "runtime-oriented" languages?

~~~
chc
I think it means "dynamic," in the sense that when you call a method, the
object's class is looked up and the class's method list is looked up and the
methods' implementations are looked up and the class is even given a chance to
handle the lookup itself. It doesn't just support reflection, it reflects
pervasively. This basically corresponds to what we usually mean when we say a
"dynamic language."

~~~
alkonaut
Is that lookup done all the time (for each invocation of the same method):? Or
is it done at a single point in time, like a JIT, but after that the method is
“fixed”?

With the possibility to intercept/replace code at runtime (at any time, not
just at a resolve/jit stage) it must be very hard for the runtime to optimize
calls (i.e make direct calls instead of indirect via method pointer lookup)?

I’m not familiar with how this works in _any_ runtime (V8, Hotspot, ...) so
I’m curious which runtimes actually pay one extra method pointer lookup
forever and which don’t. I’m guessing the answer for nearly all of them is “it
depends”.

~~~
bri3d
Many languages use "inline method caching" \- that is, a "call_dynamic
x_named_method" bytecode is replaced with a "guard_and_call_static 0xfffffff"
once the callsite is evaluated. In some languages invalidating this cache by
calling a method with polymorphic arguments or altering the receiving class
can be extremely expensive, so there are usually second-order optimizations
applied.

Objective-C: Takes one method pointer indirection / jmp trampoline forever,
but caches "selectors" on the class so that they become a simple lookup rather
than a full evaluation. See sibling comments for better write-ups than I could
find.

Most JS runtimes: Trace JITs mean many method invocations are compiled into
traces and become either inline instructions or native function calls. Also
uses "hidden classes" to implement inline method caching, where the callsite
is replaced with the specific address of the call once the dispatch is
resolved. [https://github.com/sq/JSIL/wiki/Optimizing-dynamic-
JavaScrip...](https://github.com/sq/JSIL/wiki/Optimizing-dynamic-JavaScript-
with-inline-caches) , [https://blog.ghaiklor.com/optimizations-tricks-
in-v8-d284b6c...](https://blog.ghaiklor.com/optimizations-tricks-
in-v8-d284b6c8b183)

Ruby: Also uses inline method caching - when a method is resolved that
callsite is replaced with a jump straight to the resolved method in the
bytecode. Invalidation used to occur any time a class was modified in any way
but has been made more specific over time:
[https://github.com/charliesome/charlie.bz/blob/master/posts/...](https://github.com/charliesome/charlie.bz/blob/master/posts/things-
that-clear-rubys-method-cache.md)

------
IMcD23
It's important to note that this talk is from 2016. Since then, Swift 4 has
been released, that added KVO and key paths to the language.

