Is there a way to declare an inline function in Swift?
I'm very new to the Swift language.
I wanted to declare an inline function just like in C++
so my func
declaration looks like this:
func MyFunction(param: Int) -> Int {
...
}
and I want to do something like this:
inline func MyFunction(param: Int) -> Int {
...
}
I tried to search on the web but I didn't find anything relevant maybe there is no inline
keyword but maybe there is another way to inline the function in Swift.
Solution 1:
Swift 1.2 will include the @inline
attribute, with never
and __always
as parameters. For more info, see here.
As stated before, you rarely need to declare a function explicitly as @inline(__always)
because Swift is fairly smart as to when to inline a function. Not having a function inlined, however, can be necessary in some code.
Edit: Swift 5 added the @inlinable
attribute. Make sure you read up about it, as there may be a couple of gotchas that might make in unusable. It's also only for functions/methods declared public
, so it's meant for those wanting to expose inline stuff for those that link to your library.
Solution 2:
All credit to the answer, just summarizing the information from the link.
To make a function inline just add @inline(__always)
before the function:
@inline(__always) func myFunction() {
}
However, it's worth considering and learning about the different possibilities. There are three possible ways to inline:
- sometimes - will make sure to sometimes inline the function. This is the default behavior, you don't have to do anything! Swift compiler might automatically inline functions as an optimization.
-
always - will make sure to always inline the function. Achieve this behavior by adding
@inline(__always)
before the function. Use "if your function is rather small and you would prefer your app ran faster." -
never - will make sure to never inline the function. This can be achieved by adding
@inline(never)
before the function. Use "if your function is quite long and you want to avoid increasing your code segment size."
Solution 3:
I came across an issue that i needed to use @inlinable
and @usableFromInline
attributes that were introduced in Swift 4.2 so i would like to share my experience with you.
Let me get straight to the issue though, Our codebase has a Analytics Facade module that links other modules.
App Target -> Analytics Facade module -> Reporting module X.
Analytics Facade module has a function called report(_ rawReport: EventSerializable)
that fire the reporting calls, This function uses an instance from the reporting module X to send the reporting calls for that specific reporting module X.
The thing is, calling that report(_ rawReport: EventSerializable)
function many times to send the reporting calls once the users launch the app creates unavoidable overhead that caused a lot of crashes for us.
Moreover it's not an easy task to reproduce these crashes if you are setting the Optimisation level
to None
on the debug mode. In my case i was able only to reproduce it when i set the Optimisation level
to Fastest, Smalles
t or even higher.
The solution was to use @inlinable
and @usableFromInline
.
Using @inlinable
and @usableFromInline
export the body of a function as part of a module's interface, making it available to the optimiser when referenced from other modules.
The @usableFromInline
attribute marks an internal declaration as being part of the binary interface of a module, allowing it to be used from @inlinable
code without exposing it as part of the module's source interface.
Across module boundaries, runtime generics introduce unavoidable overhead, as reified type metadata must be passed between functions, and various indirect access patterns must be used to manipulate values of generic type. For most applications, this overhead is negligible compared to the actual work performed by the code itself.
A client binary built against this framework can call those generics functions and enjoy a possible performance improvement when built with optimisations enabled, due to the elimination of abstraction overhead.
Sample Code:
@inlinable public func allEqual<T>(_ seq: T) -> Bool
where T : Sequence, T.Element : Equatable {
var iter = seq.makeIterator()
guard let first = iter.next() else { return true }
func rec(_ iter: inout T.Iterator) -> Bool {
guard let next = iter.next() else { return true }
return next == first && rec(&iter)
}
return rec(&iter)
}
More Info - Cross-module inlining and specialization