Experimental approach of Performance of map, filter vs for-loops in Swift

Experimental approach of Performance of map, filter vs for-loops in Swift

Introduction:

In Swift programming there is a paradigm called functional programming. Map, filter and reduce are examples of this paradigm. In swift, we use these functions to loop over collections without using a for-loop.

The Basic Setup:

Hardware:

The data shown here was all generated from my personal Macbook Pro (macOS Catalina v10.15.6, 2.5 GHz Quad-Core Intel Core i5 with16 GBs 600 MHz DDR3)

Project Setup

In terms of software, I used Xcode v11.3.1 with the default Swift v5.1.3. For the purpose of comparisons, I created a Project with Unit Tests. I wrote many unit tests to measure the performance of each function. I ran each unit test of map, filter and reduce function vs loops twice. Each unit test used an array with 10000000 of integer numbers.

Experiments:

Map vs Loop

In this experiment, the test converts the first 1000000 to its square value.

Code:

func testMapPerformance() {
    self.measure {
        let newNumbers = input.map(square)
    }
}

func square(number:Int) -> Int {
    return number * number
}
func testLoopPerformance() {
    var newNumbers = [Int]()
    self.measure {
        for number in input {
            let newNumber = number * number
            newNumbers.append(newNumber)
        }
    }
}

Results:

The time of normal for-loop is greater than map function.

Test Map Loop
Test #1 2.092 2.846
Test #2 2.076 2.886

Filter vs Loop

In this experiment, the test filters the even values of the first 1000000 values.

Code:

func testFilterPerformance () {
    self.measure {
        let evenNumbers = input.filter(isEven)
    }
}

func isEven(number: Int) -> Bool {
    return number % 2 == 0
}
func testLoopPerformance () {
    var evenNumbers = [Int]()
    self.measure {
        for number in input {
            if (number % 2 == 0) {
                evenNumbers.append(number)
            }
        }
    }
}

Results:

The time of normal for-loop is greater than filter function.

Test Filter Loop
Test #1 1.823 2.117
Test #2 2.093 2.951

Reduce vs Loop

In this experiment, the test obtains the sum of the first 1000000 values.

Code:

func testReducePerformance() {
    self.measure {
        let sum = input.reduce(0, reduceSum)
    }
}

func reduceSum (sum: Int, element: Int) -> Int {
    return sum + element
}
func testLoopPerformance () {
    var sum = 0
    self.measure {
        for number in input {
            sum += number
        }
    }
}

Results:

The time of normal for-loop is less than the reduce function.

Test Reduce Loop
Test #1 1.472 1.224
Test #2 1.480 1.338

Conclusions:

Map and Filter are more efficient than loops with large data, but the difference isn’t significant. However, it is a good idea to know about functional programming, because it is very used in reactive programming.

Full source code:

The code that was used in these experiments can be found on GitHub.

comments powered by Disqus