In this blog post and in future series, we will measure the performance of the recently released Swift compiler and it's runtime under Linux. We will compare selected algorithms written in C/C++ against their Swift counterpart.

Swift is nowadays apparently the most interesting programming language for iOs and Mac developers. Since it's release in 2014, it gains a lot of attraction. Now - in 12/2015 - the language is on par with Objective-C in the Tiobe popularity index. In this index Objective-C has the 14. and Swift the 15. place. This leaves pleanty room for improvements.

However, through its modern language concepts and its safe by design principle, Swift may gain more attraction to developers outside the Apple ecosystem. One important step into the right direction was made by Apple itself - the company has released Swift and additional libraries under the Apache open source license.

Ususally developers cannot be convinced by concepts and concerned with

1. Prequisites

Albeit we use Debian GNU/Linux Stretch (Testing) for our investigation, all commands shown below should also work under Ubuntu, Ubuntu LTS and other *dpkg* centric distributions.

For further informations please consider Apple's GitHub repository https://github.com/apple/swift

1.1 Installing build environment

Installing the build packages

sudo apt-get install git cmake ninja-build clang uuid-dev libicu-dev icu-devtools libbsd-dev libedit-dev libxml2-dev libsqlite3-dev swig libpython-dev libncurses5-dev pkg-config

Updating the clang compiler

sudo apt-get install clang-3.6

sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-3.6 100

sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-3.6 100

1.2 Fetching sources

Create a directory where the swift sources and the build directory can be reside.

cd ~

mkdir swift_source_root

cd swift_source_root

git clone https://github.com/apple/swift.git swift

git clone https://github.com/apple/swift-llvm.git llvm

git clone https://github.com/apple/swift-clang.git clang

git clone https://github.com/apple/swift-lldb.git lldb

git clone https://github.com/apple/swift-cmark.git cmark

git clone https://github.com/apple/swift-llbuild.git llbuild

git clone https://github.com/apple/swift-package-manager.git swiftpm

git clone https://github.com/apple/swift-corelibs-xctest.git

git clone https://github.com/apple/swift-corelibs-foundation.git

1.3 Building Swift

Swift comes with a helpful build script that compiles everything for us. The 'build-script' expects the sources to be laid out in the following way:

$SWIFT_SOURCE_ROOT/llvm

/clang

/swift

/lldb (optional)

/llbuild (optional)

/swiftpm (optional, requires llbuild)

/swift-corelibs-xctest (optional)

/swift-corelibs-foundation (optional)

The source root can be set manually by defining a environemtal varibale, e.g.

export SWIFT_SOURCE_ROOT = "$(HOME)/swift_source_root"

Since we are in the source root directory, the script automatically detects the source root. Therefore we can directly invoke the build without setting this directory

[~/swift_source_root]$ ./swift/utils/build-script -R -t

The parameters -R and -t defines to build the release version of everything. To compile for debug (default), omit the -R parameter.

[~/swift_source_root]$ ./swift/utils/build-script -t

For other build configurations conslut build-script's help.

./swift/utils/build-script -h

2. Benchmarks

In order to get a qualified statement of Swift vs. C performance, we have implemented different scenarios.

2.1 Fibonacci

The first benchmark we've implemented is the computation of a Fibonacci number.

We have implemented the recursive version of the algorithm; therefore do not expect performance wonders here - the iterative version will be much faster. For our purpose, however, it is sufficient, because it contains a lot of memory operations and function calls. Thus, this version allows us to make a statement about the performance when a lot of method are called.

Swift implementation to compute a Fibonacci number (**Fib.swift**)

func fib(number : UInt) -> UInt

{

if (number <= 2) {

return number;

}

let a = fib(number - 1);

let b = fib(number - 2);

return a + b;

} func main() { var number : UInt = 0; for argument in Process.arguments { let num:UInt? = UInt(argument) if num != nil { number = num!; } } let result = fib(number); print("fib(\(number)) = \(result)"); } main();

C implementation to compute a Fibonacci number (**Fib.c**)

#include <stdio.h>

#include <stdlib.h>



unsigned long fib(unsigned long number)

{ if (number <= 2) return number;

unsigned long a = fib(number-1);

unsigned long b = fib(number-2);

return a + b;

}





int main(int argc, char **argp)

{ unsigned long number = 0;

for (int i = 0; i < argc; i++) {

number = atoi( argp[i] );

}



unsigned long result = fib(number);

printf("fib(%lu) = %lu

", number, result);



return 0;

}

The following compilers were used:

gcc 5.2.1

clang 3.8.0

Swift 2.2-dev

To compile the examples, use the following commands:

gcc -O3 Fib.c -o Fib.gcc

clang -O3 Fib.c -o Fib.clang

swiftc -O Fib.swift

The run time of the programs can be measured with the ususal Linux "time" command. For example, to measure the time to compute the 49'th Fibonacci number you can issue:

time ./Fib.gcc 49

fib(49) = 12586269025

real 0m10.026s

user 0m10.040s sys 0m0.000s time ./Fib.clang 49

fib(49) = 12586269025

real 0m21.194s

user 0m21.228s

sys 0m0.000s time ./Fib 49

fib(49) = 12586269025

real 0m17.893s

user 0m17.920s

sys 0m0.004s

As you can see in the results for the Fibonacci workload above, the new gcc 5.2 outperforms it's competitors by approximatly the factor of 2. This is no wonder, because a lot of work was spend in the optimization over the years of it's development.

The suprising result here is that Swift outperforms clang. One would have expected that clang/LLVM should beat Swift in terms of function invocation, because Swift has inherended a dynamic invocation technique form Objective-C. The results here clearly shown that this principle performance drawback did not occur in Swift 2.0.

Future

In a future article, we will investigate the Swift compiler and the runtime in more detail with additional benchmarks. Stay tuned!