Skip to content

Commit e67460c

Browse files
committed
Finish builder and
Key Changes: - Implement Equatable, Hashable for SubSequences - Implement SortedDictionary initializers - init(keysWithValues:) and init(sortedKeysAndValues:) with named and unnamed variants. - Expand benchmark suite for SortedDictionary - Commit _BTree.Builder Minor Changes: - Update documentation - Expand test suits - Fix bug where SubSequences did not define subscript(bounds: Range<Index>) - _Node - Implement `depth` property for `_Node` - Packs both `depth`, `count`, and `capacity` within a single UInt64. - Implement `init(leftChild:seperator:rightChild:capacity:)` for `_Node` - Implement `concatenateWith(node:seperatedBy:)` to `_Node.UnsafeHandle` - Remove bad invariant check on `_Node.UnsafeHandle` deletion subroutines - _BTree - Add invariant checks as `_BTree.checkInvariants()` - Separate `_BTree.*capacity` into `*size` and `*capacity` - Make _FixedSizeArray top-level - Remove deque behavior. Documentation: - Update complexity documentation style from 'n' to `self.count` Testing: - Expand tests for SortedDictionary - Add tests for SortedDictionary.Keys - Add tests for _Node.join(...) routines - Add tests for _BTree.Builder - Restore checkBidirectionalCollection tests for _BTree
1 parent 0d0d66f commit e67460c

37 files changed

+1894
-383
lines changed

Benchmarks/Benchmarks/SortedDictionaryBenchmarks.swift

Lines changed: 229 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -10,64 +10,247 @@
1010
//===----------------------------------------------------------------------===//
1111

1212
import CollectionsBenchmark
13+
import SortedCollections
1314

1415
extension Benchmark {
1516
public mutating func addSortedDictionaryBenchmarks() {
16-
// self.add(
17-
// title: "SortedDictionary<Int, Int> init(uniqueKeysWithValues:)",
18-
// input: [Int].self
19-
// ) { input in
20-
// let keysAndValues = input.lazy.map { (key: $0, value: 2 * $0) }
21-
//
22-
// return { timer in
23-
// blackHole(SortedDictionary(uniqueKeysWithValues: keysAndValues))
24-
// }
25-
// }
26-
//
27-
// self.add(
28-
// title: "SortedDictionary<Int, Int> subscript, append",
29-
// input: [Int].self
30-
// ) { input in
31-
// let keysAndValues = input.lazy.map { (key: $0, value: 2 * $0) }
32-
// var sortedDictionary = SortedDictionary<Int, Int>()
33-
//
34-
// return { timer in
35-
// for (key, value) in keysAndValues {
36-
// sortedDictionary[key] = value
37-
// }
38-
// blackHole(sortedDictionary)
39-
// }
40-
// }
41-
//
42-
// self.add(
43-
// title: "SortedDictionary<Int, Int> subscript, successful lookups",
44-
// input: ([Int], [Int]).self
45-
// ) { input, lookups in
46-
// let keysAndValues = input.lazy.map { (key: $0, value: 2 * $0) }
47-
// let sortedDictionary = SortedDictionary<Int, Int>(uniqueKeysWithValues: keysAndValues)
48-
//
49-
// return { timer in
50-
// for key in lookups {
51-
// precondition(sortedDictionary._root.contains(key: key))
52-
// }
53-
// }
54-
// }
17+
self.add(
18+
title: "SortedDictionary<Int, Int> init(keysWithValues:)",
19+
input: [Int].self
20+
) { input in
21+
let keysAndValues = input.lazy.map { (key: $0, value: 2 * $0) }
22+
23+
return { timer in
24+
blackHole(SortedDictionary(keysWithValues: keysAndValues))
25+
}
26+
}
5527

5628
self.add(
57-
title: "SortedDictionary<Int, Int>._BTree subscript, successful lookups",
58-
input: ([Int], [Int]).self
59-
) { input, lookups in
29+
title: "SortedDictionary<Int, Int> init(sortedKeysWithValues:)",
30+
input: Int.self
31+
) { input in
32+
let keysAndValues = (0..<input).lazy.map { (key: $0, value: 2 * $0) }
33+
34+
return { timer in
35+
blackHole(SortedDictionary(sortedKeysWithValues: keysAndValues))
36+
}
37+
}
38+
39+
self.add(
40+
title: "SortedDictionary<Int, Int> sequential iteration",
41+
input: [Int].self
42+
) { input in
6043
let keysAndValues = input.lazy.map { (key: $0, value: 2 * $0) }
61-
var tree = _BTree<Int, Int>()
44+
let d = SortedDictionary(keysWithValues: keysAndValues)
6245

63-
for (k, v) in keysAndValues {
64-
tree.setAnyValue(v, forKey: k)
46+
return { timer in
47+
for item in d {
48+
blackHole(item)
49+
}
6550
}
51+
}
52+
53+
self.add(
54+
title: "SortedDictionary<Int, Int> forEach iteration",
55+
input: [Int].self
56+
) { input in
57+
let keysAndValues = input.lazy.map { (key: $0, value: 2 * $0) }
58+
let d = SortedDictionary(keysWithValues: keysAndValues)
59+
60+
return { timer in
61+
d.forEach({ blackHole($0) })
62+
}
63+
}
64+
65+
self.add(
66+
title: "SortedDictionary<Int, Int>.Keys sequential iteration",
67+
input: [Int].self
68+
) { input in
69+
let keysAndValues = input.lazy.map { (key: $0, value: 2 * $0) }
70+
let d = SortedDictionary(keysWithValues: keysAndValues)
71+
72+
return { timer in
73+
for item in d.keys {
74+
blackHole(item)
75+
}
76+
}
77+
}
78+
79+
self.add(
80+
title: "SortedDictionary<Int, Int>.Values sequential iteration",
81+
input: [Int].self
82+
) { input in
83+
let keysAndValues = input.lazy.map { (key: $0, value: 2 * $0) }
84+
let d = SortedDictionary(keysWithValues: keysAndValues)
85+
86+
return { timer in
87+
for item in d.values {
88+
blackHole(item)
89+
}
90+
}
91+
}
6692

93+
self.add(
94+
title: "SortedDictionary<Int, Int> subscript, successful lookups",
95+
input: ([Int], [Int]).self
96+
) { input, lookups in
97+
let sortedDictionary = SortedDictionary(
98+
keysWithValues: input.map { ($0, 2 * $0) })
99+
100+
return { timer in
101+
for key in lookups {
102+
precondition(sortedDictionary[key] == key * 2)
103+
}
104+
}
105+
}
106+
107+
self.add(
108+
title: "SortedDictionary<Int, Int> subscript, unsuccessful lookups",
109+
input: ([Int], [Int]).self
110+
) { input, lookups in
111+
let sortedDictionary = SortedDictionary(
112+
keysWithValues: input.map { ($0, 2 * $0) })
113+
114+
let c = input.count
67115
return { timer in
68116
for key in lookups {
69-
precondition(tree.contains(key: key))
117+
precondition(sortedDictionary[key + c] == nil)
118+
}
119+
}
120+
}
121+
122+
self.add(
123+
title: "SortedDictionary<Int, Int> subscript, setter append",
124+
input: [Int].self
125+
) { input in
126+
let keysAndValues = input.lazy.map { (key: $0, value: 2 * $0) }
127+
var sortedDictionary = SortedDictionary<Int, Int>()
128+
129+
return { timer in
130+
for (key, value) in keysAndValues {
131+
sortedDictionary[key] = value
132+
}
133+
blackHole(sortedDictionary)
134+
}
135+
}
136+
137+
self.add(
138+
title: "SortedDictionary<Int, Int> subscript, setter noop",
139+
input: ([Int], [Int]).self
140+
) { input, lookups in
141+
return { timer in
142+
var d = SortedDictionary(
143+
keysWithValues: input.map { ($0, 2 * $0) })
144+
145+
let c = input.count
146+
timer.measure {
147+
for i in lookups {
148+
d[i + c] = nil
149+
}
150+
}
151+
precondition(d.count == input.count)
152+
blackHole(d)
153+
}
154+
}
155+
156+
self.add(
157+
title: "SortedDictionary<Int, Int> subscript, setter update",
158+
input: ([Int], [Int]).self
159+
) { input, lookups in
160+
return { timer in
161+
var d = SortedDictionary(
162+
keysWithValues: input.map { ($0, 2 * $0) })
163+
164+
timer.measure {
165+
for i in lookups {
166+
d[i] = 0
167+
}
168+
}
169+
precondition(d.count == input.count)
170+
blackHole(d)
171+
}
172+
}
173+
174+
self.add(
175+
title: "SortedDictionary<Int, Int> subscript, setter remove",
176+
input: ([Int], [Int]).self
177+
) { input, lookups in
178+
return { timer in
179+
var d = SortedDictionary(
180+
keysWithValues: input.map { ($0, 2 * $0) })
181+
182+
timer.measure {
183+
for i in lookups {
184+
d[i] = nil
185+
}
186+
}
187+
precondition(d.count == 0)
188+
blackHole(d)
189+
}
190+
}
191+
192+
self.add(
193+
title: "SortedDictionary<Int, Int> subscript, _modify insert",
194+
input: ([Int], [Int]).self
195+
) { input, lookups in
196+
return { timer in
197+
var d = SortedDictionary<Int, Int>()
198+
199+
@inline(__always)
200+
func modify(_ i: inout Int?, to value: Int?) {
201+
i = value
202+
}
203+
204+
timer.measure {
205+
for i in lookups {
206+
modify(&d[i], to: i * 2)
207+
}
208+
}
209+
210+
precondition(d.count == input.count)
211+
blackHole(d)
212+
}
213+
}
214+
215+
self.add(
216+
title: "SortedDictionary<Int, Int> subscript, _modify update",
217+
input: ([Int], [Int]).self
218+
) { input, lookups in
219+
return { timer in
220+
var d = SortedDictionary(
221+
keysWithValues: input.map { ($0, 2 * $0) })
222+
223+
timer.measure {
224+
for i in lookups {
225+
d[i]! *= 2
226+
}
227+
}
228+
precondition(d.count == input.count)
229+
blackHole(d)
230+
}
231+
}
232+
233+
self.add(
234+
title: "SortedDictionary<Int, Int> subscript, _modify remove",
235+
input: ([Int], [Int]).self
236+
) { input, lookups in
237+
return { timer in
238+
var d = SortedDictionary(
239+
keysWithValues: input.map { ($0, 2 * $0) })
240+
241+
@inline(__always)
242+
func modify(_ i: inout Int?, to value: Int?) {
243+
i = value
244+
}
245+
246+
timer.measure {
247+
for i in lookups {
248+
modify(&d[i], to: nil)
249+
}
70250
}
251+
252+
precondition(d.count == 0)
253+
blackHole(d)
71254
}
72255
}
73256
}

Sources/SortedCollections/BTree/_BTree+BidirectionalCollection.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ extension _BTree: BidirectionalCollection {
5353
return Index(
5454
node: currentNode,
5555
slot: 0,
56-
childSlots: FixedSizeArray(repeating: 0, depth: depth),
56+
childSlots: _FixedSizeArray(repeating: 0, depth: depth),
5757
offset: 0,
5858
forTree: self
5959
)
@@ -195,4 +195,10 @@ extension _BTree: BidirectionalCollection {
195195
precondition(index != endIndex, "Attempt to subscript out of range index.")
196196
return index.element
197197
}
198+
199+
@inlinable
200+
@inline(__always)
201+
internal subscript(bounds: Range<Index>) -> SubSequence {
202+
return SubSequence(base: self, bounds: bounds)
203+
}
198204
}

0 commit comments

Comments
 (0)