Run Swiftly: precompiled Swift actions

The OpenWhisk serverless platform allows developers to run functions coded in different languages in the “cloud” without deploying or managing servers. The platform today offers first class support for Node.js, Python, Swift and Java.

An example of a Swift action in OpenWhisk is the following main function which returns a greeting:

Swift actions, unlike other actions, have an expensive startup latency (called the “cold start” latency) which is incurred by the swiftc compiler. Using the CLI for a blocking invoke which returns the full activation record, the time spent executing the action is stored in the duration property. The activation above for helloSwift took nearly 3 seconds. Invoking the action again, we can see the action benefits from a “warm start” and the activation is much faster (28 milliseconds):

I previously described a way to run precompiled binaries as OpenWhisk actions in this article but I will reprise it here for Swift actions. The methodology is mostly the same but I adapt it to allow for dynamic linking against the Swift runtime and libraries so that actions are smaller and leaner.

I’ll use the same hello.swift action — the goal is to precompile the binary and use it to run a Swift action. This will eschew the expensive compilation step and get the execution time of the action to be closer to the warm start instead.

To do this, we will need Docker to run the Swift action container locally. This will allow us to build the binary in the same environment that it will eventually run within, when using OpenWhisk.

The steps above provide a recipe for compiling and linking the action and creating a Zip file from the resultant executable called Action. The build script swiftbuildandlink.sh expects the source code in a file called main.swift. You will need to tweak the script if you have more than one source file. The executable must be located at .build/release/Action inside the archive.

With the Zip file, you can now create a new Swift action from it and invoke it as before: