Skip to content

Commit 4804425

Browse files
committed
[benchmark] Add regular (slow) Unmanaged variant
1 parent 2e95ab9 commit 4804425

File tree

1 file changed

+97
-12
lines changed

1 file changed

+97
-12
lines changed

benchmark/single-source/RandomTree.swift

Lines changed: 97 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,13 @@ public let RandomTree = [
2626
tags: [.validation, .algorithm, .refcount],
2727
setUpFunction: { blackHole(input) }),
2828
BenchmarkInfo(
29-
name: "RandomTree.insert.Unmanaged",
30-
runFunction: run_Unmanaged_insert,
29+
name: "RandomTree.insert.Unmanaged.slow",
30+
runFunction: run_SlowUnmanaged_insert,
31+
tags: [.validation, .algorithm, .refcount],
32+
setUpFunction: { blackHole(input) }),
33+
BenchmarkInfo(
34+
name: "RandomTree.insert.Unmanaged.fast",
35+
runFunction: run_FastUnmanaged_insert,
3136
tags: [.validation, .algorithm, .refcount],
3237
setUpFunction: { blackHole(input) }),
3338
BenchmarkInfo(
@@ -80,24 +85,93 @@ extension EnumSearchTree {
8085
}
8186
}
8287

83-
struct UnmanagedSearchTree<Element: Comparable> {
88+
struct SlowUnmanagedSearchTree<Element: Comparable> {
89+
class Node {
90+
var value: Element
91+
var left: SlowUnmanagedSearchTree
92+
var right: SlowUnmanagedSearchTree
93+
94+
init(
95+
value: Element,
96+
left: SlowUnmanagedSearchTree = .empty,
97+
right: SlowUnmanagedSearchTree = .empty
98+
) {
99+
self.left = left
100+
self.right = right
101+
self.value = value
102+
}
103+
}
104+
105+
static var empty: SlowUnmanagedSearchTree<Element> { SlowUnmanagedSearchTree() }
106+
107+
var root: Unmanaged<Node>?
108+
109+
init() {
110+
self.root = nil
111+
}
112+
113+
init(_root: Unmanaged<Node>?) {
114+
self.root = _root
115+
}
116+
}
117+
118+
extension SlowUnmanagedSearchTree {
119+
mutating func deallocate() {
120+
guard let root = root?.takeRetainedValue() else { return }
121+
root.left.deallocate()
122+
root.right.deallocate()
123+
}
124+
}
125+
126+
extension SlowUnmanagedSearchTree {
127+
func forEach(_ body: (Element) -> Void) {
128+
guard let root = root?.takeUnretainedValue() else { return }
129+
root.left.forEach(body)
130+
body(root.value)
131+
root.right.forEach(body)
132+
}
133+
134+
func contains(_ value: Element) -> Bool {
135+
guard let root = root?.takeUnretainedValue() else { return false }
136+
if value == root.value { return true }
137+
return value < root.value
138+
? root.left.contains(value)
139+
: root.right.contains(value)
140+
}
141+
142+
mutating func insert(_ value: __owned Element) {
143+
guard let root = root?.takeUnretainedValue() else {
144+
self.root = Unmanaged.passRetained(Node(value: value))
145+
return
146+
}
147+
if value == root.value {
148+
return
149+
} else if value < root.value {
150+
root.left.insert(value)
151+
} else {
152+
root.right.insert(value)
153+
}
154+
}
155+
}
156+
157+
struct FastUnmanagedSearchTree<Element: Comparable> {
84158
class Node {
85159
var value: Element
86-
var left: UnmanagedSearchTree
87-
var right: UnmanagedSearchTree
160+
var left: FastUnmanagedSearchTree
161+
var right: FastUnmanagedSearchTree
88162

89163
init(
90164
value: Element,
91-
left: UnmanagedSearchTree = .empty,
92-
right: UnmanagedSearchTree = .empty
165+
left: FastUnmanagedSearchTree = .empty,
166+
right: FastUnmanagedSearchTree = .empty
93167
) {
94168
self.left = left
95169
self.right = right
96170
self.value = value
97171
}
98172
}
99173

100-
static var empty: UnmanagedSearchTree<Element> { UnmanagedSearchTree() }
174+
static var empty: FastUnmanagedSearchTree<Element> { FastUnmanagedSearchTree() }
101175

102176
var root: Unmanaged<Node>?
103177

@@ -110,7 +184,7 @@ struct UnmanagedSearchTree<Element: Comparable> {
110184
}
111185
}
112186

113-
extension UnmanagedSearchTree {
187+
extension FastUnmanagedSearchTree {
114188
mutating func deallocate() {
115189
guard let root = root else { return }
116190
root._withUnsafeGuaranteedRef { root in
@@ -121,7 +195,7 @@ extension UnmanagedSearchTree {
121195
}
122196
}
123197

124-
extension UnmanagedSearchTree {
198+
extension FastUnmanagedSearchTree {
125199
func forEach(_ body: (Element) -> Void) {
126200
guard let root = root else { return }
127201
root._withUnsafeGuaranteedRef { root in
@@ -231,9 +305,20 @@ func run_ADT_insert(_ iterations: Int) {
231305
}
232306
}
233307

234-
func run_Unmanaged_insert(_ iterations: Int) {
308+
func run_SlowUnmanaged_insert(_ iterations: Int) {
309+
for _ in 0 ..< iterations {
310+
var tree = identity(SlowUnmanagedSearchTree<Int>.empty)
311+
for value in input {
312+
tree.insert(value)
313+
}
314+
blackHole(tree)
315+
tree.deallocate()
316+
}
317+
}
318+
319+
func run_FastUnmanaged_insert(_ iterations: Int) {
235320
for _ in 0 ..< iterations {
236-
var tree = identity(UnmanagedSearchTree<Int>.empty)
321+
var tree = identity(FastUnmanagedSearchTree<Int>.empty)
237322
for value in input {
238323
tree.insert(value)
239324
}

0 commit comments

Comments
 (0)