Skip to content

Commit

Permalink
[stdlib] Sort Arrays using bulk mutation backdoor
Browse files Browse the repository at this point in the history
This results in a a massive speedup and could in principle be applied to
other bulk array mutations.

Swift SVN r18926
  • Loading branch information
Dave Abrahams committed Jun 16, 2014
1 parent 9603472 commit c5c17e2
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 19 deletions.
49 changes: 40 additions & 9 deletions stdlib/core/Algorithm.swift
Original file line number Diff line number Diff line change
Expand Up @@ -170,15 +170,39 @@ struct Less<T: Comparable> {
}
}

func sort<
C: MutableCollection where C.IndexType: RandomAccessIndex
>(
inout collection: C,
pred: (C.GeneratorType.Element, C.GeneratorType.Element) -> Bool
) {
quickSort(&collection, indices(collection), pred)
}

func sort<
C: MutableCollection
where C.IndexType: RandomAccessIndex, C.GeneratorType.Element: Comparable
>(
inout collection: C
) {
quickSort(&collection, indices(collection))
}

func sort<T>(inout array: T[], pred: (T, T) -> Bool) {
quickSort(&array, 0..array.count, pred)
return array.withMutableStorage {
a in sort(&a, pred)
return
}
}

/// The functions below are a copy of the functions above except that
/// they don't accept a predicate and they are hardcoded to use the less-than
/// comparator.
func sort<T : Comparable>(inout array: T[]) {
quickSort(&array, 0..array.count)
return array.withMutableStorage {
a in sort(&a)
return
}
}

func sorted<
Expand All @@ -188,7 +212,7 @@ func sorted<
pred: (C.GeneratorType.Element, C.GeneratorType.Element) -> Bool
) -> C {
var result = source
quickSort(&result, indices(result), pred)
sort(&result, pred)
return result
}

Expand All @@ -197,7 +221,7 @@ func sorted<
where C.GeneratorType.Element: Comparable, C.IndexType: RandomAccessIndex
>(source: C) -> C {
var result = source
quickSort(&result, indices(result))
sort(&result)
return result
}

Expand All @@ -208,7 +232,7 @@ func sorted<
pred: (S.GeneratorType.Element, S.GeneratorType.Element) -> Bool
) -> S.GeneratorType.Element[] {
var result = Array(source)
quickSort(&result, indices(result), pred)
sort(&result, pred)
return result
}

Expand All @@ -219,7 +243,7 @@ func sorted<
source: S
) -> S.GeneratorType.Element[] {
var result = Array(source)
quickSort(&result, indices(result))
sort(&result)
return result
}

Expand Down Expand Up @@ -308,14 +332,21 @@ func partition<
return i.pred()
}

func quickSort<C: MutableCollection where C.GeneratorType.Element: Comparable, C.IndexType: RandomAccessIndex>(
func quickSort<
C: MutableCollection
where C.GeneratorType.Element: Comparable, C.IndexType: RandomAccessIndex
>(
inout elements: C,
range: Range<C.IndexType>) {
_quickSort(&elements, range)
}

func _quickSort<C: MutableCollection where C.GeneratorType.Element: Comparable, C.IndexType: RandomAccessIndex>(
inout elements: C, range: Range<C.IndexType>) {
func _quickSort<
C: MutableCollection
where C.GeneratorType.Element: Comparable, C.IndexType: RandomAccessIndex
>(
inout elements: C, range: Range<C.IndexType>
) {
// Insertion sort is better at handling smaller regions.
let cnt = count(range)
if cnt < 20 {
Expand Down
18 changes: 8 additions & 10 deletions stdlib/core/Arrays.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -355,16 +355,14 @@ extension ${Self} {
}

extension ${Self} {
mutating func withMutableStorage<R>(body: (UnsafeMutableArray<T>)->R) -> R {
if _slowPath(!_buffer.isMutableAndUniquelyReferenced()) {
{
self._buffer = _Buffer(ContiguousArray(self)._buffer)
}()
}
return _buffer.withUnsafePointerToElements {
[count = self.count] in
body(UnsafeMutableArray(start: $0, length: count))
}
mutating func withMutableStorage<R>(
body: (inout UnsafeMutableArray<T>)->R
) -> R {
_arrayReserve(&_buffer, 0)
var a = UnsafeMutableArray(start: _buffer.elementStorage, length: count)
let ret = body(&a)
_fixLifetime(_buffer)
return ret
}
}
%end
Expand Down

0 comments on commit c5c17e2

Please sign in to comment.