About Veronica Ray

Veronica Ray is a software engineer at LinkedIn. She honed her functional programming chops in Scala and is excited about developing on iOS with Swift. Once she rode her bike between two moose. Follow her on Medium and Twitter: @nerdonica.

List Comprehensions and Performance With Swift

This post written on August 15, 2015 to be compatible with Xcode 6 and Swift 1.2

List comprehensions provide a concise way to create lists. You can accomplish list comprehension-like operations in Swift even though list comprehensions are not mentioned in the Swift language guide.

Say you want to create a list of squares, like:

var squares = [Int]()
for x in 1..<10 {
    squares.append(x*x)
}

In Python you could use a list comprehension instead

squares = [x**2 for x in range(10)]

In Swift you can do

let squares = Array(map(1..<10) { $0 * $0 })

To get the sum of all the elements in the list you could do this

var sum = 0
for square in squares {
    sum = sum + square
}

Or use the reduce function

let sum = squares.reduce(0, { $0 + $1 })

Like list comprehensions in some other languages, you can use any Sequence or Collection as the input, not just a Range.

You can use map/reduce/filter/stride depending on what kind of list you are trying to create.

The two main perks of list comprehensions are conciseness and being able to generate faster bitcode.

My imitation list comprehension was more concise. I was curious whether it would also generate faster bitcode.

This article showed me how to analyze Swift assembly code using Hopper, an OSX and Linux disassembler. You can try Hopper for free without buying a license.

The code snippets without list comprehensions and with the imitation list comprehensions generated the same assembly code.

The assembly code from Hopper

Since both snippets created the same assembly code I assumed their execution time would be the same. We can demontrate this by measuring the execution of our program using XCTest.

My test for the code snippet with no list comprehension

func testNoListComprehensionPerformance() {
    self.measureBlock() {
        var squares = [Int]()
        for x in 1...5 {
            squares.append(x)
        }
    }
}

The relevant output

Test Case '-[speedTestTests.speedTestTests testNoListComprehensionPerformance]' started.

:0: Test Case '-[speedTestTests.speedTestTests testNoListComprehensionPerformance]' measured [Time, seconds] average: 0.000, relative standard deviation: 236.965%, values: [0.000154, 0.000005, 0.000004, 0.000004, 0.000004, 0.000004, 0.000004, 0.000004, 0.000004, 0.000004], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100
Test Case '-[speedTestTests.speedTestTests testNoListComprehensionPerformance]' passed (0.262 seconds).

My test for the code snippet with the imitation list comprehension

Test Case '-[speedTestTests.speedTestTests testSortaListComprehensionPerformance]' started.

:0: Test Case '-[speedTestTests.speedTestTests testSortaListComprehensionPerformance]' measured [Time, seconds] average: 0.000, relative standard deviation: 160.077%, values: [0.000045, 0.000005, 0.000004, 0.000003, 0.000003, 0.000003, 0.000003, 0.000004, 0.000003, 0.000003], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100
Test Case '-[speedTestTests.speedTestTests testSortaListComprehensionPerformance]' passed (0.255 seconds).

On average they only differ by only 0.007 seconds.

The coolest application of list comprehensions I've seen is in a spelling corrector. Airspeed Velocity wrote a Swift version of Peter Norvig's Python spelling corrector.

Conciseness is the main benefit of using list comprehension-like operations in Swift. Paul Graham wrote a great essay about how conciseness in programming languages is power. Since each programmer can only write a certain number of lines of code per day, you can accomplish more each day if you can accomplish more in the same number of lines. This power also makes you rethink what programs are possible. In a more verbose language this spelling corrector example could have seemed like an overwhelming project. I love how how something as technically complex and mysterious as a spelling corrector can be expressed in so few lines of code in Swift.


Sign up now and get a set of FREE video tutorials on writing iOS apps coming soon.



Subscribe via RSS