Performance of iterators in -Onone

SR-8742, regarding the performance of iterators and for loops in -Onone, has been open for a couple of years, and has been causing major issues in the iteration cycle for an app I'm working on. To briefly summarise, code like the following:

@inline(never)
func doSomething(_ x: Int) {
    print(x)
}

func loopElements(iterations: Int) {
    for i in 0..<iterations {
        doSomething(i)
    }
}

gets compiled down (Godbolt) to calls to IndexingIterator.nextElement, which in turn means a lot of protocol method lookups, eventual calls to the _read accessor, and resulting malloc/free calls for each iteration of the loop. Needless to say, this is very slow.

I've poked around in the compiler for ways to enforce that for loops over ranges of integers (and ideally ranges that have had basic Sequence operations applied to them such as reversed() or prefix) get compiled down to, well, a for loop, but haven't had any success. This post is therefore mainly to draw attention to this issue in the hope that someone more knowledgeable can take a look at it or suggest a fix. I know -Onone is meant to be unoptimised, but I think this probably passes the threshold of "should be optimised unconditionally".

1 Like