Monday, May 6, 2024

Swift’s Native Clocks Are Very Inefficient

Wade Tregaskis (Hacker News):

In a nutshell, the problem is that Swift’s Clock protocol has significant overheads by design. If you look at a time profile of code like this, you’ll see things like[…]

That’s a lot of time wasted in function calls and struct initialisation and type conversion and protocol witnesses and all that guff. The only part that’s actually retrieving the time is the swift_get_time call (which is just a wrapper over clock_gettime, which is just a wrapper over clock_gettime_nsec_np(CLOCK_UPTIME_RAW), which is just a wrapper over mach_absolute_time).


The downside to calling mach_absolute_timedirectly, though, is that it’s on Apple’s “naughty” list – apparently it’s been abused for device fingerprinting, so Apple require you to beg for special permission if you want to use it (even though it’s used by all these other APIs anyway, as the basis for their implementations, and there’s nothing you can get from mach_absolute_time that you can’t get from them too 🤨).

This matches my experience that intuition is often wrong regarding Swift performance. Sometimes what seems like it would be a simple virtual call has more overhead than an Objective-C message send. Various dynamic stuff involving checking types/protocols can also be much slower than with Objective-C. The good news is that Date is fast, not even calling down to NSDate, and that there’s a pull request to inline some of this.


1 Comment RSS · Twitter · Mastodon

I agree on the Swift performance thing. We’re at a point now where I consider anything Swift to be slow, until proven otherwise. When the Swift team released their embedded version for Playdate it came the claim that it was performant. So I asked for some figures: of course there were none. It was just an assumption on their part: it’s Swift, so it must be performant. I measured the performance and it ran at 60% of the speed of the C version it was a port of. Embarrassing.

Leave a Comment