Skip to content

Marking synchronous implementation of AsyncIteratorProtocol with "await" makes it much slower #70484

Open
@saagarjha

Description

@saagarjha

Description

I have an AsyncSequence that is actually fully synchronous (shown below). If I implement next() without async and compile with optimizations then iterating over it easily hits a billion or more iterations per second. However, if I mark next() as async (and make no other changes) then it runs 3-4 orders of magnitude slower.

Reproduction

struct TestSequence: AsyncSequence {
	struct AsyncIterator: AsyncIteratorProtocol {
		var iterator = (1...(.max)).makeIterator()

		mutating func next() -> Element? {
			iterator.next()
		}
	}

	func makeAsyncIterator() -> AsyncIterator {
		AsyncIterator()
	}

	typealias Element = Int
}

let sequence = TestSequence()

var last = 0
var lastTime = ContinuousClock.Instant.now

for await n in sequence where n % 1_000 == 0 {
	if ContinuousClock.Instant.now - lastTime > .seconds(1) {
		print(n - last, "iterations per second")
		last = n
		lastTime = ContinuousClock.Instant.now
	}
}

Expected behavior

If I add async to next() and compile with optimizations then I expect the same performance as the code above.

Environment

$ swiftc -version
swift-driver version: 1.87.3 Apple Swift version 5.9.2 (swiftlang-5.9.2.2.56 clang-1500.1.0.2.5)
Target: arm64-apple-macosx14.0

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.concurrencyFeature: umbrella label for concurrency language featuresperformance

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions