Cool zero-cost abstractions in Swift?

I recently read an article on Rust's zero-cost abstractions. This made me wonder what kind of cool zero-cost abstractions Swift has?

The point of listing these would be to ensure that one doesn't prematurely optimize by avoiding a particular abstraction or language construct, thinking that said construct would cost performance.

Examples could be:

  • passing non-escaping closures to stdlib functions (e.g. forEach or map) should be just as fast iterating manually
  • structs that wrap scalar types should be just as fast as the type itself

A non-zero-cost abstraction could be protocols, because passing them to another function incurs additional overhead wrapping the argument in a witness object.

4 Likes

A cool zero-size-cost abstraction are enums

How big is a pointer on my machine? 8 bytes.

print(MemoryLayout<UnsafeRawPointer>.size) // 8

How big is a pointer + info about if it's a some case or none case? Also 8

print(MemoryLayout<UnsafeRawPointer?>.size) // 8

Compiler realizes that the bitpattern of all zeros is unsused in UnsafeRawPointer, so it can be used to represent none case. That way you don't need to add an additional byte to keep track the case of an enum, which would be needed for something that uses up all bits of the size.

You could wonder - Are optional pointers a special case? No! :) It also works with enums other than Optional:

enum Foo {
    case something(UnsafeRawPointer)
    case nothing
}
print(MemoryLayout<Foo>.size) // 8

and with things that aren't pointers

enum A {
    case a
    case b
}
enum B {
    case c
    case d
}
enum C {
    case e(A)
    case f(B)
}
print(MemoryLayout<A>.size) // 1
print(MemoryLayout<C>.size) // 1
4 Likes

Good tool for checking if an abstraction is truly zero-cost is compiler explorer at godbolt.org

For example you can see that using loops and addition instead of multiplication is zero-cost on -Ounchecked, but not on -O

1 Like