Skip to content

[WIP][stdlib] Minor Sequence Optimizations #20758

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 24 additions & 22 deletions stdlib/public/core/Sequence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,18 @@ extension Sequence where Element : Equatable {
}
}

extension ContiguousArray {
/// Rotates array in place to the left by specified distance.
@usableFromInline
mutating func _rotate(left distance: Int) {
guard distance > 0 else { return }
let i = index(startIndex, offsetBy: distance)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not necessarily the best way to rotate, and is probably not the API we want to commit to supporting even internally. Please try to use what's already written in the algorithms prototype, and especially read this comment and test accordingly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it's better than to split this and do just the consistent use of ContiguousArray in this PR, and tackle the in-place rotation in a separate PR, right?

self[startIndex..<i].reverse()
self[i..<endIndex].reverse()
self.reverse()
}
}

extension Sequence {

/// Returns the longest possible subsequences of the sequence, in order, that
Expand Down Expand Up @@ -889,10 +901,9 @@ extension Sequence {

// FIXME: <rdar://problem/21885650> Create reusable RingBuffer<T>
// Put incoming elements into a ring buffer to save space. Once all
// elements are consumed, reorder the ring buffer into an `Array`
// and return it. This saves memory for sequences particularly longer
// than `maxLength`.
var ringBuffer: [Element] = []
// elements are consumed, reorder the ring buffer and return it.
// This saves memory for sequences particularly longer than `maxLength`.
var ringBuffer = ContiguousArray<Element>()
ringBuffer.reserveCapacity(Swift.min(maxLength, underestimatedCount))

var i = 0
Expand All @@ -902,20 +913,12 @@ extension Sequence {
ringBuffer.append(element)
} else {
ringBuffer[i] = element
i += 1
i %= maxLength
i = (i + 1) % maxLength
}
}

if i != ringBuffer.startIndex {
var rotated: [Element] = []
rotated.reserveCapacity(ringBuffer.count)
rotated += ringBuffer[i..<ringBuffer.endIndex]
rotated += ringBuffer[0..<i]
return rotated
} else {
return ringBuffer
}
ringBuffer._rotate(left: i)
return Array(ringBuffer)
}

/// Returns a sequence containing all but the given number of initial
Expand Down Expand Up @@ -972,8 +975,8 @@ extension Sequence {
// holding tank into the result, an `Array`. This saves
// `k` * sizeof(Element) of memory, because slices keep the entire
// memory of an `Array` alive.
var result: [Element] = []
var ringBuffer: [Element] = []
var result = ContiguousArray<Element>()
var ringBuffer = ContiguousArray<Element>()
var i = ringBuffer.startIndex

for element in self {
Expand All @@ -982,11 +985,10 @@ extension Sequence {
} else {
result.append(ringBuffer[i])
ringBuffer[i] = element
i += 1
i %= k
i = (i + 1) % k
}
}
return result
return Array(result)
}

/// Returns a sequence by skipping the initial, consecutive elements that
Expand Down Expand Up @@ -1068,15 +1070,15 @@ extension Sequence {
public __consuming func prefix(
while predicate: (Element) throws -> Bool
) rethrows -> [Element] {
var result: [Element] = []
var result = ContiguousArray<Element>()

for element in self {
guard try predicate(element) else {
break
}
result.append(element)
}
return result
return Array(result)
}
}

Expand Down