Swift for loop runs slow

Hey, so I created a for loop in swift which adds values from 1 to 1000000 in an empty array and then I print the array. But for some reason it runs really slow. And if I do it until 100 it's fast. But still that's the slowest I have seen-in other programming languages it's instant. Is it that Swift is slower or do I have to use some library I am not using?

1 Like

Welcome to the community!

You’ll want to make sure that you call array.reserveCapacity(1000000) before you start doing the insertions otherwise the array will need to be resized many times throughout the operation which is expensive. Give that a try and see if performance improves.

Also how are you measuring the performance? If you can share the actual code that would be helpful.

2 Likes

I just ran the following snippet and it took around 19 seconds which surprised me. But weirdly, when I run it in the regular macOS terminal (I was using iTerm initially) or the integrated terminal in my nvim instance, it runs in exactly 0.34s. So if you're using iTerm, it may be a bug with iTerm.

var array: [Int] = []
for i in 0..<1000000 {
    array.append(i)
}
print(array)

There are of course ways to optimise this code (as patrick has pointed out), but I was just taking a best guess at what you might be running.

If you're timing the execution of that program, you're including the print statement.

I assumed that they were measuring the execution of the whole program so that's what I did too. The print statement should still be faster than 19 seconds, and it seems to only be in iTerm that it's actually slow on my machine.

Just want to point out that if you don't reference the array (e.g. the print statement) you might get a very fast runtime indeed if the optimiser decides you aren't using the result of that loop (YMMV)... But a print of array.count would suffice :-)

You can always do:

@inline(never) func blackHole(_: some Any) {}

blackHole(array)
1 Like

no I am doing it in Xcode I don't know what that is using

yeah I am using print

I tried but it's the same here is code

import Cocoa

var number=0
let counter=1
var currentcount=0

var myArray:[Int]=[]

myArray.reserveCapacity(1000000)

while number<=1000000{
    myArray.insert(counter*currentcount, at: currentcount)
    currentcount+=1
    number+=1
}

for element in myArray{
    print(element)
}










Are you running in a Playground? Running in a Playground will cause your code to run much more slowly than it would in 'real life'.

3 Likes

oh I see ok then that's the issue probably. Yeah it's in a playground. Ok then well this is to test my swift skills anyway it's not anything real I am trying to make so I will just leave it at 100 and move on to coding other stuff in Swift. I was just testing my skills in playground before actually coding something else in Swift because I am new and I have never coded in Swift. But I have code in C# and Java and Python for example. Thanks for clarifying!

2 Likes

The benefit you get for the slower execution is that you get to see things like how many times each line was executed and what historical values different expressions took on for the duration of the execution, which can make it a good place to learn about how Swift code is functioning.

2 Likes

oh I see that's the point. Yeah that makes sense

Also, if you want the entire code to be more performant, you could combine all the prints into one. For print to be thread-safe, it locks during each invocation, meaning that you perform an atomic operation for each element of the array. The compiler might be able to optimize that, but to be safe, write whatever you want to print on a string and then print that. This way you also avoid any dynamic lookup that could happen to convert Int into a string.

IIRC that only works if blackHole(_:) is in a different module than your code

(Edit: can we provide this API in the stdlib, with some compiler support to mean "no really, please never ever inline this, no not even in that case, no no that one either, please just don't optimize out my performance tests"?)

2 Likes

Also note that if you switch from playgrounds to a regular project (which you should do) you'll also need to build in Release mode to run at full speed. It defaults to an unoptimized build for debugging.

4 Likes