Skip to content

Commit f73d5e9

Browse files
authored
Add reference benchmarks for bit vector implementations (apple#79)
* [benchmark] Reorganize C++/Foundation benchmarks into separate files * [benchmark] Add reference benchmarks for std::vector<bool> and CFBitVector * Fix thinko breaking non-Darwin builds
1 parent cc69069 commit f73d5e9

15 files changed

+1484
-711
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift Collections open source project
4+
//
5+
// Copyright (c) 2021 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
//
10+
//===----------------------------------------------------------------------===//
11+
12+
import CollectionsBenchmark
13+
import CppBenchmarks
14+
15+
extension Benchmark {
16+
public mutating func addCppBenchmarks() {
17+
cpp_set_hash_fn { value in value._rawHashValue(seed: 0) }
18+
19+
self.addSimple(
20+
title: "std::hash<intptr_t>",
21+
input: [Int].self
22+
) { input in
23+
input.withUnsafeBufferPointer { buffer in
24+
cpp_hash(buffer.baseAddress, buffer.count)
25+
}
26+
}
27+
28+
self.addSimple(
29+
title: "custom_intptr_hash (using Swift.Hasher)",
30+
input: [Int].self
31+
) { input in
32+
input.withUnsafeBufferPointer { buffer in
33+
cpp_custom_hash(buffer.baseAddress, buffer.count)
34+
}
35+
}
36+
37+
_addCppVectorBenchmarks()
38+
_addCppDequeBenchmarks()
39+
_addCppUnorderedSetBenchmarks()
40+
_addCppUnorderedMapBenchmarks()
41+
_addCppPriorityQueueBenchmarks()
42+
_addCppVectorBoolBenchmarks()
43+
}
44+
}
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift Collections open source project
4+
//
5+
// Copyright (c) 2021 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
//
10+
//===----------------------------------------------------------------------===//
11+
12+
import CollectionsBenchmark
13+
import CppBenchmarks
14+
15+
internal class CppDeque {
16+
var ptr: UnsafeMutableRawPointer?
17+
18+
init(_ input: [Int]) {
19+
self.ptr = input.withUnsafeBufferPointer { buffer in
20+
cpp_deque_create(buffer.baseAddress, buffer.count)
21+
}
22+
}
23+
24+
deinit {
25+
destroy()
26+
}
27+
28+
func destroy() {
29+
if let ptr = ptr {
30+
cpp_deque_destroy(ptr)
31+
}
32+
ptr = nil
33+
}
34+
}
35+
36+
extension Benchmark {
37+
internal mutating func _addCppDequeBenchmarks() {
38+
self.addSimple(
39+
title: "std::deque<intptr_t> push_back from integer range",
40+
input: Int.self
41+
) { count in
42+
cpp_deque_from_int_range(count)
43+
}
44+
45+
self.addSimple(
46+
title: "std::deque<intptr_t> constructor from buffer",
47+
input: [Int].self
48+
) { input in
49+
input.withUnsafeBufferPointer { buffer in
50+
cpp_deque_from_int_buffer(buffer.baseAddress, buffer.count)
51+
}
52+
}
53+
54+
self.add(
55+
title: "std::deque<intptr_t> sequential iteration",
56+
input: [Int].self
57+
) { input in
58+
let deque = CppDeque(input)
59+
return { timer in
60+
cpp_deque_iterate(deque.ptr)
61+
}
62+
}
63+
64+
self.add(
65+
title: "std::deque<intptr_t> random-access offset lookups (operator [])",
66+
input: ([Int], [Int]).self
67+
) { input, lookups in
68+
let vector = CppDeque(input)
69+
return { timer in
70+
lookups.withUnsafeBufferPointer { buffer in
71+
cpp_deque_lookups_subscript(vector.ptr, buffer.baseAddress, buffer.count)
72+
}
73+
}
74+
}
75+
76+
self.add(
77+
title: "std::deque<intptr_t> at, random offsets",
78+
input: ([Int], [Int]).self
79+
) { input, lookups in
80+
let deque = CppDeque(input)
81+
return { timer in
82+
lookups.withUnsafeBufferPointer { buffer in
83+
cpp_deque_lookups_at(deque.ptr, buffer.baseAddress, buffer.count)
84+
}
85+
}
86+
}
87+
88+
self.addSimple(
89+
title: "std::deque<intptr_t> push_back",
90+
input: [Int].self
91+
) { input in
92+
input.withUnsafeBufferPointer { buffer in
93+
cpp_deque_append_integers(buffer.baseAddress, buffer.count)
94+
}
95+
}
96+
97+
self.addSimple(
98+
title: "std::deque<intptr_t> push_front",
99+
input: [Int].self
100+
) { input in
101+
input.withUnsafeBufferPointer { buffer in
102+
cpp_deque_prepend_integers(buffer.baseAddress, buffer.count)
103+
}
104+
}
105+
106+
self.addSimple(
107+
title: "std::deque<intptr_t> random insertions",
108+
input: Insertions.self
109+
) { insertions in
110+
insertions.values.withUnsafeBufferPointer { buffer in
111+
cpp_deque_random_insertions(buffer.baseAddress, buffer.count)
112+
}
113+
}
114+
115+
self.add(
116+
title: "std::deque<intptr_t> pop_back",
117+
input: Int.self
118+
) { size in
119+
return { timer in
120+
let deque = CppDeque(Array(0 ..< size))
121+
timer.measure {
122+
cpp_deque_pop_back(deque.ptr)
123+
}
124+
deque.destroy()
125+
}
126+
}
127+
128+
self.add(
129+
title: "std::deque<intptr_t> pop_front",
130+
input: Int.self
131+
) { size in
132+
return { timer in
133+
let deque = CppDeque(Array(0 ..< size))
134+
timer.measure {
135+
cpp_deque_pop_front(deque.ptr)
136+
}
137+
deque.destroy()
138+
}
139+
}
140+
141+
self.add(
142+
title: "std::deque<intptr_t> random removals",
143+
input: Insertions.self
144+
) { insertions in
145+
let removals = Array(insertions.values.reversed())
146+
return { timer in
147+
let deque = CppDeque(Array(0 ..< removals.count))
148+
timer.measure {
149+
removals.withUnsafeBufferPointer { buffer in
150+
cpp_deque_random_removals(deque.ptr, buffer.baseAddress, buffer.count)
151+
}
152+
}
153+
deque.destroy()
154+
}
155+
}
156+
157+
self.add(
158+
title: "std::deque<intptr_t> sort",
159+
input: [Int].self
160+
) { input in
161+
return { timer in
162+
let deque = CppDeque(input)
163+
timer.measure {
164+
cpp_deque_sort(deque.ptr)
165+
}
166+
deque.destroy()
167+
}
168+
}
169+
}
170+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift Collections open source project
4+
//
5+
// Copyright (c) 2021 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
//
10+
//===----------------------------------------------------------------------===//
11+
12+
import CollectionsBenchmark
13+
import CppBenchmarks
14+
15+
internal class CppPriorityQueue {
16+
var ptr: UnsafeMutableRawPointer?
17+
18+
init(_ input: [Int]) {
19+
self.ptr = input.withUnsafeBufferPointer { buffer in
20+
cpp_priority_queue_create(buffer.baseAddress, buffer.count)
21+
}
22+
}
23+
24+
convenience init() {
25+
self.init([])
26+
}
27+
28+
deinit {
29+
destroy()
30+
}
31+
32+
func destroy() {
33+
if let ptr = ptr {
34+
cpp_priority_queue_destroy(ptr)
35+
}
36+
ptr = nil
37+
}
38+
39+
func push(_ value: Int) {
40+
cpp_priority_queue_push(ptr, value)
41+
}
42+
43+
func push(_ values: [Int]) {
44+
values.withUnsafeBufferPointer { buffer in
45+
cpp_priority_queue_push_loop(ptr, buffer.baseAddress, buffer.count)
46+
}
47+
}
48+
49+
func pop() -> Int {
50+
cpp_priority_queue_pop(ptr)
51+
}
52+
53+
func popAll() {
54+
cpp_priority_queue_pop_all(ptr)
55+
}
56+
}
57+
58+
extension Benchmark {
59+
internal mutating func _addCppPriorityQueueBenchmarks() {
60+
self.addSimple(
61+
title: "std::priority_queue<intptr_t> construct from buffer",
62+
input: [Int].self
63+
) { input in
64+
let pq = CppPriorityQueue(input)
65+
blackHole(pq)
66+
}
67+
68+
self.add(
69+
title: "std::priority_queue<intptr_t> push",
70+
input: [Int].self
71+
) { input in
72+
return { timer in
73+
let pq = CppPriorityQueue()
74+
timer.measure {
75+
pq.push(input)
76+
}
77+
blackHole(pq)
78+
pq.destroy()
79+
}
80+
}
81+
82+
self.add(
83+
title: "std::priority_queue<intptr_t> pop",
84+
input: [Int].self
85+
) { input in
86+
return { timer in
87+
let pq = CppPriorityQueue(input)
88+
timer.measure {
89+
pq.popAll()
90+
}
91+
blackHole(pq)
92+
pq.destroy()
93+
}
94+
}
95+
}
96+
}

0 commit comments

Comments
 (0)