swift

This past WWDC Apple revealed a brand new programming language called Swift to the masses and passed it out to Apple Developers packaged in the XCode 6 Beta.

Language Features

  • Type Inferencing and Automatic Reference Counting (ARC)
  • Optional Bindings and Generic Functions
  • Integration with Objective-C
  • First-Class Functions and Closures

My initial impressions were pretty high. However, after some quick benchmarking examples, those feelings later matured to an understanding of it’s "beta" characteristics. Many of the underlying optimization still have some kinks to work through.

And by kinks, I mean some big fixes

Benchmarks

Here are a couple examples of Bubble Sort written out in C, Python and Swift.

Swift Bubble Sort

import Foundation

func exchange<T>(inout a: T, inout b: T)
{
    let tmp = a
    a = b
    b = tmp
}

func bubbleSort(inout array: [Int]) -> [Int]
{
    let length = array.count

    var count, pos: Int
    for (count=0; count<length-1; count++)
    {
        for (pos=0; pos<(length-count-1); pos++)
        {
            if (array[pos] > array[pos+1]) {
                exchange(&array[pos], &array[pos+1])
            }
        }
    }
    return array
}

func sortMain(arrayLength: Int) -> [Int]
{
    var array: [Int] = []
    for _ in 0..<arrayLength {
        array.append(
            Int(arc4random_uniform(UInt32(arrayLength*100)))
        )
    }
    return bubbleSort(&array)
}

C Bubble Sort

#include <stdio.h>
#include <stdlib.h>

void bubble_sort(long list[], long n)
{
    long count, pos, temp;
    for (count = 0; count < (n-1); count++) {
        for (pos = 0; pos < (n-count-1); pos++) {
            if (list[pos] > list[pos+1])
            {
                temp        =   list[pos];
                list[pos]   =   list[pos+1];
                list[pos+1] =   temp;
            }
        }
    }
}

int main(int argc, char *argv[])
{
    long problem_size = strtoul(argv[1], NULL, 10);
    long array[problem_size];
    long count;

    sranddev();
    for (count = 0; count < problem_size; count++) {
        array[count] = rand() % problem_size;
    }

    bubble_sort(array, problem_size);

    for (count = 0; count < problem_size; count++) {
        printf("%ld\n", array[count]);
    }
    return 0;
}

Python Bubble Sort

import os
import sys

from random import randint

def bubble_sort(array):
    length = len(array)
    for count in range(0, length):
        for pos in range(0, length-count-1):
            if array[pos] > array[pos + 1]:
                (array[pos], array[pos+1]) = (array[pos+1], array[pos])
    return array

def main(array_size):
    array = [
        randint(0, array_size)
            for num in range(0, array_size)
    ]
    return bubble_sort(array)


if __name__ == '__main__':
    sys.exit(main(int(sys.argv[1])))

Fast Swift:

Swift vs C vs PyPy
Swift Program is Swift, It even beats C by a non-trivial margin in these tests.

Slow Swift:

Swift [-Ofast] vs Swift[-O3] vs CPython

One caveat however, is we used the [-Ofast] flag during compilation of the swift binaries like so.

xcrun --sdk macosx swift -Ofast -o bubble_sort.swift bubble_sort

According to Apple’s official documentation in the XCode 5.0 release notes:

A new optimization level -Ofast, available in LLVM, enables aggressive optimizations. -Ofast relaxes some conservative restrictions, mostly for floating-point operations, that are safe for most code. It can yield significant high-performance wins from the compiler

If we were to run the same code with normal compiler optimizations we start to see a completely different picture than the one we started with

xcrun --sdk macosx swift -O3 -o bubble_sort.swift bubble_sort

Note

In order to save time, I’ve changed the problem sizes to be multiples of 1k rather than 10k, so that tests could finish reasonibly quick. Other than that nothing has changed.

Modern, Safe and Powerful: Choose 2

swift_principles

According to a post on Stacked Overflow

However, -Ofast changes the semantics of the language a lot — in my testing, it disabled the checks for integer overflows and array indexing overflows. For example, with -Ofast the following Swift code runs silently without crashing (and prints out some garbage):
let n = 10000000
println(n*n*n*n*n)
let x = Int[](count: n, repeatedValue: 10)
println(x[n])
  • With -Ofast I get pretty much what I would expect. The relevant part is a loop with 5 machine language instructions.
  • With -O3 I get something that was beyond my wildest imagination. The inner loop spans 88 lines of assembly code. I did not try to understand all of it, but the most suspicious parts are 13 invocations of callq _swift_retain" and another 13 invocations of "callq _swift_release". That is, 26 subroutine calls in the inner loop!

Comments

comments powered by Disqus