Skip to content

Commit 78eca77

Browse files
committed
[cxx-interop] Create benchmarks for using std::span in Swift
Also adds test to use-std-span.swift
1 parent b191390 commit 78eca77

File tree

6 files changed

+151
-0
lines changed

6 files changed

+151
-0
lines changed

benchmark/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ set(SWIFT_BENCH_MODULES
214214
cxx-source/CxxVectorSum
215215
# TODO: rdar://92120528
216216
# cxx-source/ReadAccessor
217+
cxx-source/CxxSpanTests
217218
)
218219

219220
set(SWIFT_MULTISOURCE_SWIFT_BENCHES
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
//===--- CxxSpanTests.swift ----------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2023 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+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import TestsUtils
14+
import CxxStdlibPerformance
15+
import CxxStdlib
16+
17+
let iterRepeatFactor = 7
18+
19+
public let benchmarks = [
20+
BenchmarkInfo(
21+
name: "CxxSpanTests.raw.iterator",
22+
runFunction: rawIterator,
23+
tags: [.validation, .bridging, .cxxInterop],
24+
setUpFunction: makeSpanOnce),
25+
BenchmarkInfo(
26+
name: "CxxSpanTests.index.subscript",
27+
runFunction: indexAndSubscript,
28+
tags: [.validation, .bridging, .cxxInterop],
29+
setUpFunction: makeSpanOnce),
30+
BenchmarkInfo(
31+
name: "CxxSpanTests.for.loop",
32+
runFunction: forInLoop,
33+
tags: [.validation, .bridging, .cxxInterop],
34+
setUpFunction: makeSpanOnce),
35+
BenchmarkInfo(
36+
name: "CxxSpanTests.map",
37+
runFunction: mapSpan,
38+
tags: [.validation, .bridging, .cxxInterop],
39+
setUpFunction: makeSpanOnce),
40+
BenchmarkInfo(
41+
name: "CxxSpanTests.filter",
42+
runFunction: filterSpan,
43+
tags: [.validation, .bridging, .cxxInterop],
44+
setUpFunction: makeSpanOnce),
45+
BenchmarkInfo(
46+
name: "CxxSpanTests.reduce",
47+
runFunction: reduceSpan,
48+
tags: [.validation, .bridging, .cxxInterop],
49+
setUpFunction: makeSpanOnce)
50+
]
51+
52+
func makeSpanOnce() {
53+
initSpan()
54+
}
55+
56+
@inline(never)
57+
public func rawIterator(_ n: Int) {
58+
var sum: UInt32 = 0
59+
for _ in 0..<(n * iterRepeatFactor) {
60+
var b = span.__beginUnsafe()
61+
let e = span.__endUnsafe()
62+
while b != e {
63+
sum = sum &+ b.pointee
64+
b = b.successor()
65+
}
66+
}
67+
blackHole(sum)
68+
}
69+
70+
@inline(never)
71+
public func indexAndSubscript(_ n: Int) {
72+
var sum: UInt32 = 0
73+
for _ in 0..<(n * iterRepeatFactor) {
74+
for i in 0..<span.size() {
75+
sum = sum &+ span[i]
76+
}
77+
}
78+
blackHole(sum)
79+
}
80+
81+
@inline(never)
82+
public func forInLoop(_ n: Int) {
83+
var sum: UInt32 = 0
84+
for _ in 0..<(n * iterRepeatFactor) {
85+
for x in span {
86+
sum = sum &+ x
87+
}
88+
}
89+
blackHole(sum)
90+
}
91+
92+
@inline(never)
93+
public func mapSpan(_ n: Int) {
94+
for _ in 0..<(n * iterRepeatFactor) {
95+
let result = span.map { $0 + 5 }
96+
blackHole(result)
97+
}
98+
}
99+
100+
@inline(never)
101+
public func filterSpan(_ n: Int) {
102+
for _ in 0..<(n * iterRepeatFactor) {
103+
let result = span.filter { $0 % 2 == 0 }
104+
blackHole(result)
105+
}
106+
}
107+
108+
@inline(never)
109+
public func reduceSpan(_ n: Int) {
110+
var sum: UInt32 = 0
111+
for _ in 0..<(n * iterRepeatFactor) {
112+
sum = sum &+ span.reduce(sum, &+)
113+
}
114+
blackHole(sum)
115+
}

benchmark/utils/CxxTests/CxxStdlibPerformance.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,19 @@
33
#include <cstdint>
44
#include <vector>
55
#include <set>
6+
#include <span>
67

8+
static const size_t spanSize = 25000;
9+
10+
using ArrayOfU32 = uint32_t[spanSize];
711
using VectorOfU32 = std::vector<uint32_t>;
812
using SetOfU32 = std::set<uint32_t>;
13+
using SpanOfU32 = std::span<uint32_t>;
914

15+
static inline ArrayOfU32 array;
1016
static inline VectorOfU32 vec;
1117
static inline SetOfU32 set;
18+
static inline SpanOfU32 span;
1219

1320
inline void initVector(size_t size) {
1421
if (!vec.empty()) {
@@ -29,6 +36,16 @@ inline void initSet(size_t size) {
2936
}
3037
}
3138

39+
inline void initSpan() {
40+
if (!span.empty()) {
41+
return;
42+
}
43+
for (size_t i = 0; i < spanSize; ++i) {
44+
array[i] = uint32_t(i);
45+
}
46+
span = SpanOfU32(array);
47+
}
48+
3249
inline VectorOfU32 makeVector32(size_t size) {
3350
initVector(size);
3451
return vec;

benchmark/utils/main.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ import CreateObjects
6060
import CxxStringConversion
6161
// rdar://128520766
6262
// import CxxVectorSum
63+
import CxxSpanTests
6364
import DataBenchmarks
6465
import DeadArray
6566
import DevirtualizeProtocolComposition
@@ -258,6 +259,7 @@ register(CreateObjects.benchmarks)
258259
register(CxxStringConversion.benchmarks)
259260
// rdar://128520766
260261
// register(CxxVectorSum.benchmarks)
262+
register(CxxSpanTests.benchmarks)
261263
register(DataBenchmarks.benchmarks)
262264
register(DeadArray.benchmarks)
263265
register(DevirtualizeProtocolComposition.benchmarks)

test/Interop/Cxx/stdlib/Inputs/std-span.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ inline Span initSpan() {
5050
return Span(a);
5151
}
5252

53+
inline Span initSpan(int arr[], size_t size) {
54+
return Span(arr, size);
55+
}
56+
5357
inline struct SpanBox getStructSpanBox() { return {iarray, iarray, sarray, sarray}; }
5458

5559
#endif // TEST_INTEROP_CXX_STDLIB_INPUTS_STD_SPAN_H

test/Interop/Cxx/stdlib/use-std-span.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,18 @@ StdSpanTestSuite.test("Init SpanOfInt") {
176176
expectFalse(cs.empty())
177177
}
178178

179+
StdSpanTestSuite.test("Init SpanOfInt from Swift array") {
180+
var arr: [Int32] = [1, 2, 3]
181+
arr.withUnsafeMutableBufferPointer{ ubpointer in
182+
let s = initSpan(ubpointer.baseAddress!, ubpointer.count)
183+
expectEqual(s.size(), 3)
184+
expectFalse(s.empty())
185+
expectEqual(s[0], 1)
186+
expectEqual(s[1], 2)
187+
expectEqual(s[2], 3)
188+
}
189+
}
190+
179191
StdSpanTestSuite.test("Access static SpanOfInt") {
180192
expectEqual(icspan.size(), 3)
181193
expectFalse(icspan.empty())

0 commit comments

Comments
 (0)