Performance improvements and cleanup for queue.

This commit is contained in:
Krunoslav Zaher 2015-08-12 20:51:47 +02:00
parent c4b392c86d
commit d9efe90751
2 changed files with 32 additions and 14 deletions

View File

@ -23,11 +23,10 @@ public struct Queue<T>: SequenceType {
initialCapacity = capacity
version = 0
storage = []
_count = 0
pushNextIndex = 0
resizeTo(capacity)
storage = [T?](count: capacity, repeatedValue: nil)
}
private var dequeueIndex: Int {
@ -56,19 +55,20 @@ public struct Queue<T>: SequenceType {
}
mutating private func resizeTo(size: Int) {
var newStorage: [T?] = []
newStorage.reserveCapacity(size)
var newStorage = [T?](count: size, repeatedValue: nil)
var count = _count
for var i = 0; i < count; ++i {
// does swift array have some more efficient methods of copying?
newStorage.append(dequeue())
}
let dequeueIndex = self.dequeueIndex
let spaceToEndOfQueue = self.storage.count - dequeueIndex
while newStorage.count < size {
newStorage.append(nil)
}
// first batch is from dequeue index to end of array
let countElementsInFirstBatch = min(count, spaceToEndOfQueue)
// second batch is wrapped from start of array to end of queue
let numberOfElementsInSecondBatch = count - countElementsInFirstBatch
newStorage[0 ..< countElementsInFirstBatch] = self.storage[dequeueIndex ..< (dequeueIndex + countElementsInFirstBatch)]
newStorage[countElementsInFirstBatch ..< (countElementsInFirstBatch + numberOfElementsInSecondBatch)] = self.storage[0 ..< numberOfElementsInSecondBatch]
_count = count
pushNextIndex = count
@ -92,11 +92,11 @@ public struct Queue<T>: SequenceType {
}
}
public mutating func dequeue() -> T {
private mutating func dequeueElementOnly() -> T {
version++
contract(count > 0)
let index = dequeueIndex
let value = storage[index]!
@ -104,6 +104,12 @@ public struct Queue<T>: SequenceType {
_count = _count - 1
return value
}
public mutating func dequeue() -> T {
let value = dequeueElementOnly()
let downsizeLimit = storage.count / (resizeFactor * resizeFactor)
if _count < downsizeLimit && downsizeLimit >= initialCapacity {
resizeTo(storage.count / resizeFactor)

View File

@ -47,4 +47,16 @@ extension QueueTest {
XCTAssertEqual(queue.count, 200 - i - 1)
}
}
func testComplexity() {
var queue: Queue<Int> = Queue(capacity: 2)
XCTAssertEqual(queue.count, 0)
for var i = 0; i < 200000; ++i {
queue.enqueue(i)
}
XCTAssertEqual(Array(0 ..< 200000), Array(queue))
}
}