Swift 1.2: Faster Executables

iNVASIVECODE
[cocoa gurus]
Published in
4 min readMar 5, 2015

--

An iOS SDK Tutorial

Swift 1.2 was announced a couple of weeks ago. Now, you can download it together with Xcode 6.3 beta 2 from the developer portal.

As I read about the new features for Swift 1.2 in the Swift blog for Apple Developers, one highlight feature captured my attention. It reads:

  • Faster executables — Debug builds produces binaries that run considerably faster, and new optimizations deliver even better Release build performance.

So, faster debug builds, great. But I’m more interested in Release build optimization. Can Swift execute faster than C?

This is the important question, especially for me. I develop image processing and pattern recognition algorithms for mobile applications, and the number of operations involved are usually really huge. For example, if an image has a size of 640x480 pixels in grayscale, one has to process 307200 pixels. And if you perform a convolution (a very common operation in image processing) between this image and a kernel of size 15x15 pixels, you end up performing 225(=15x15) multiplications and 224(= 14*15+14) additions for each pixel of the 640x480 image.

Now, imagine performing a convolution in real-time, processing the frames from the video camera of your iPhone. An algorithm that processes such rapid images must execute really, really fast to match the 30 frames/s of your iPhone camera. Of course, you can use the GPU (and actually, you should), but not every algorithm can run on the GPU.

Swift to the rescue!

Let’s see how Swift performs on these algorithms compared to C in Release mode. Here, I will compare Swift performance against C performance for image processing algorithms.

I have compared, many times, a few of my C algorithms to their Swift version, and the speed comparison always favored the C implementation. But now, we have Swift 1.2, with its “Faster executables” feature. So, I downloaded Xcode 6.3 beta 2 and I updated my code to Swift 1.2 using the provided script (you can find it in Edit -> Convert -> To Latest Swift… and follow the wizard — very straightforward).

As a testing algorithm, I chose the Otsu’s thresholding algorithm, which I have for both C and Swift. I created a performance test using the -measureBlock method and ran the test on an iPhone 6 in Release Mode and set the compiler optimization to -Ofast.

self.measureBlock() {
// Image processing
let threshold = self.vc.otsuThresholdForImage(bitmap, width: w, height: h)
self.vc.thresholdImage(bitmap, width: w, height: h, threshold: threshold)
}

The first method inside the closure computes the threshold value as explained here. The second methodthresholdImage(_:, width:, height:, threshold☺ applies the threshold to the entire image:

func thresholdImage(bitmap: UnsafeMutablePointer<UInt8>, width w: UInt, height h: UInt, threshold value: Int) -> UnsafeMutablePointer<UInt8> {
let result = UnsafeMutablePointer<UInt8>.alloc(Int(w*h))
for i in 0 ..< Int(h) {
for j in 0 ..< Int(w) {
result[i * Int(w) + j] = bitmap[i * Int(w) + j] <= UInt8(value) ? 255 : 0
}
}
return result
}

As you might know, measureBlock executes 10 times the block of code inside the closure. I then ran the algorithm on images with different size: 640x480, 1920x1200, 3008x2000, 4544x1952, 4542x3907. Here’s a small table with the results:

Image size    Swift 1.1         Swift 1.2         C
640x400 0.002s(8% STDEV) 0.002s(17% STDEV) 0.002s(12% STDEV)
1920x1200 0.021s(10% STDEV) 0.019s(5% STDEV) 0.013s(10% STDEV)
3008x2000 0.049s(3% STDEV) 0.047s(6% STDEV) 0.034s(16% STDEV)
4544x1952 0.072s(5% STDEV) 0.067s(8% STDEV) 0.046s(11% STDEV)
4542x3907 0.142s(6% STDEV) 0.139s(8% STDEV) 0.094s(12% STDEV)

So, unfortunately, there was nothing really exciting. I repeated the same tests for other image processing algorithms and the results showed, as highlighted in the previous table, similar relative differences.

Notice that the increase of number of pixels (larger image size) increases the difference between Swift 1.2 and C. So, C executes faster when the number of data increases.

Also notice that difference between Swift 1.1 and 1.2 is not really significative.

In Debug mode, the results are completely different. There, Swift 1.2 is incredibly faster than Swift 1.1 (almost 4–5x). But, again this is Debug mode. Nothing really interesting for the final applications.

C remains faster in Release mode for this type of algorithms, and there is a slight improvement between Swift 1.1 and 1.2. Of course, this new version of Swift comes with the tools still in beta, so there’s still space for improvement. But when will Swift beat C?

Geppy

Geppy Parziale (@geppyp) is cofounder of InvasiveCode. He develops iOS applications and teaches iOS development since 2008. He worked at Apple as iOS and OS X Engineer in the Core Recognition team. He has developed several iOS and OS X apps and frameworks for Apple, and many of his development projects are top-grossing iOS apps that are featured in the App Store.

--

--

iNVASIVECODE
[cocoa gurus]

iOS consulting and training. Expertise include: machine vision, pattern-recognition, biometrics, and loT.