Skip to content

Commit 635237c

Browse files
committed
Merge remote-tracking branch 'origin/main' into swift/main
2 parents 4290d8e + 7a10c81 commit 635237c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+2672
-1369
lines changed

Sources/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,4 @@
22
add_subdirectory(RegexBuilder)
33
add_subdirectory(_RegexParser)
44
add_subdirectory(_StringProcessing)
5-
add_subdirectory(Prototypes)
65
add_subdirectory(VariadicsGenerator)

Sources/RegexBenchmark/Benchmark.swift

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,45 @@
1-
import _StringProcessing
1+
@_spi(RegexBenchmark) import _StringProcessing
2+
@_implementationOnly import _RegexParser
23
import Foundation
34

4-
protocol RegexBenchmark {
5+
protocol RegexBenchmark: Debug {
56
var name: String { get }
67
func run()
7-
func debug()
88
}
99

10-
struct Benchmark: RegexBenchmark {
10+
protocol SwiftRegexBenchmark: RegexBenchmark {
11+
var regex: Regex<AnyRegexOutput> { get set }
12+
var pattern: String? { get }
13+
}
14+
15+
extension SwiftRegexBenchmark {
16+
mutating func compile() {
17+
let _ = regex._forceAction(.recompile)
18+
}
19+
mutating func parse() -> Bool {
20+
guard let s = pattern else {
21+
return false
22+
}
23+
24+
do {
25+
let _ = try _RegexParser.parse(s, .traditional)
26+
return true
27+
} catch {
28+
return false
29+
}
30+
}
31+
mutating func enableTracing() {
32+
let _ = regex._forceAction(.addOptions(.enableTracing))
33+
}
34+
mutating func enableMetrics() {
35+
let _ = regex._forceAction(.addOptions([.enableMetrics]))
36+
}
37+
}
38+
39+
struct Benchmark: SwiftRegexBenchmark {
1140
let name: String
12-
let regex: Regex<AnyRegexOutput>
41+
var regex: Regex<AnyRegexOutput>
42+
let pattern: String?
1343
let type: MatchType
1444
let target: String
1545

@@ -52,11 +82,12 @@ struct NSBenchmark: RegexBenchmark {
5282
}
5383

5484
/// A benchmark running a regex on strings in input set
55-
struct InputListBenchmark: RegexBenchmark {
85+
struct InputListBenchmark: SwiftRegexBenchmark {
5686
let name: String
57-
let regex: Regex<AnyRegexOutput>
87+
var regex: Regex<AnyRegexOutput>
88+
let pattern: String?
5889
let targets: [String]
59-
90+
6091
func run() {
6192
for target in targets {
6293
blackHole(target.wholeMatch(of: regex))
@@ -78,7 +109,7 @@ struct InputListNSBenchmark: RegexBenchmark {
78109
func range(in target: String) -> NSRange {
79110
NSRange(target.startIndex..<target.endIndex, in: target)
80111
}
81-
112+
82113
func run() {
83114
for target in targets {
84115
let range = range(in: target)
@@ -89,6 +120,9 @@ struct InputListNSBenchmark: RegexBenchmark {
89120

90121
/// A benchmark meant to be ran across multiple engines
91122
struct CrossBenchmark {
123+
/// Suffix added onto NSRegularExpression benchmarks
124+
static var nsSuffix: String { "_NS" }
125+
92126
/// The base name of the benchmark
93127
var baseName: String
94128

@@ -123,11 +157,12 @@ struct CrossBenchmark {
123157
Benchmark(
124158
name: baseName + "Whole",
125159
regex: swiftRegex,
160+
pattern: regex,
126161
type: .whole,
127162
target: input))
128163
runner.register(
129164
NSBenchmark(
130-
name: baseName + "Whole_NS",
165+
name: baseName + "Whole" + CrossBenchmark.nsSuffix,
131166
regex: nsRegex,
132167
type: .first,
133168
target: input))
@@ -136,24 +171,26 @@ struct CrossBenchmark {
136171
Benchmark(
137172
name: baseName + "All",
138173
regex: swiftRegex,
174+
pattern: regex,
139175
type: .allMatches,
140176
target: input))
141177
runner.register(
142178
NSBenchmark(
143-
name: baseName + "All_NS",
179+
name: baseName + "All" + CrossBenchmark.nsSuffix,
144180
regex: nsRegex,
145181
type: .allMatches,
146182
target: input))
147-
if includeFirst {
183+
if includeFirst || runner.includeFirstOverride {
148184
runner.register(
149185
Benchmark(
150186
name: baseName + "First",
151187
regex: swiftRegex,
188+
pattern: regex,
152189
type: .first,
153190
target: input))
154191
runner.register(
155192
NSBenchmark(
156-
name: baseName + "First_NS",
193+
name: baseName + "First" + CrossBenchmark.nsSuffix,
157194
regex: nsRegex,
158195
type: .first,
159196
target: input))
@@ -178,10 +215,11 @@ struct CrossInputListBenchmark {
178215
runner.register(InputListBenchmark(
179216
name: baseName,
180217
regex: swiftRegex,
218+
pattern: regex,
181219
targets: inputs
182220
))
183221
runner.register(InputListNSBenchmark(
184-
name: baseName + "NS",
222+
name: baseName + CrossBenchmark.nsSuffix,
185223
regex: regex,
186224
targets: inputs
187225
))
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2021-2022 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+
#if os(macOS) && canImport(Charts)
13+
14+
import Charts
15+
import SwiftUI
16+
17+
struct BenchmarkChart: View {
18+
var comparisons: [BenchmarkResult.Comparison]
19+
20+
// Sort by normalized difference
21+
var sortedComparisons: [BenchmarkResult.Comparison] {
22+
comparisons.sorted { a, b in
23+
a.normalizedDiff < b.normalizedDiff
24+
}
25+
}
26+
var body: some View {
27+
VStack(alignment: .leading) {
28+
Chart {
29+
ForEach(sortedComparisons) { comparison in
30+
// Normalized runtime
31+
BarMark(
32+
x: .value("Name", comparison.name),
33+
y: .value("Normalized runtime", comparison.normalizedDiff))
34+
.foregroundStyle(LinearGradient(
35+
colors: [.accentColor, comparison.diff?.seconds ?? 0 <= 0 ? .green : .yellow],
36+
startPoint: .bottom,
37+
endPoint: .top))
38+
}
39+
// Baseline
40+
RuleMark(y: .value("Time", 1.0))
41+
.foregroundStyle(.red)
42+
.lineStyle(.init(lineWidth: 1, dash: [2]))
43+
.annotation(position: .top, alignment: .leading) {
44+
Text("Baseline").foregroundStyle(.red)
45+
}
46+
47+
}
48+
.frame(idealWidth: 800, idealHeight: 800)
49+
.chartYScale(domain: 0...2.0)
50+
.chartYAxis {
51+
AxisMarks(values: .stride(by: 0.1))
52+
}
53+
.chartXAxis {
54+
AxisMarks { value in
55+
AxisGridLine()
56+
AxisTick()
57+
AxisValueLabel(value.as(String.self)!, orientation: .vertical)
58+
}
59+
}
60+
}
61+
}
62+
}
63+
64+
struct BenchmarkResultApp: App {
65+
static var comparisons: [BenchmarkResult.Comparison]?
66+
67+
var body: some Scene {
68+
WindowGroup {
69+
if let comparisons = Self.comparisons {
70+
ScrollView {
71+
BenchmarkChart(comparisons: comparisons)
72+
}
73+
} else {
74+
Text("No data")
75+
}
76+
}
77+
}
78+
}
79+
80+
#endif

Sources/RegexBenchmark/BenchmarkRegistration.swift

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,22 @@
22
// Do not remove the start of registration or end of registration markers
33

44
extension BenchmarkRunner {
5-
static func makeRunner(
6-
_ samples: Int,
7-
_ quiet: Bool
8-
) -> BenchmarkRunner {
9-
var benchmark = BenchmarkRunner("RegexBench", samples, quiet)
5+
mutating func registerDefault() {
106
// -- start of registrations --
11-
benchmark.addReluctantQuant()
12-
benchmark.addCSS()
13-
benchmark.addNotFound()
14-
benchmark.addGraphemeBreak()
15-
benchmark.addHangulSyllable()
16-
// benchmark.addHTML() // Disabled due to \b being unusably slow
17-
benchmark.addEmail()
18-
benchmark.addCustomCharacterClasses()
19-
benchmark.addBuiltinCC()
20-
benchmark.addUnicode()
21-
benchmark.addLiteralSearch()
22-
benchmark.addDiceNotation()
23-
benchmark.addErrorMessages()
24-
benchmark.addIpAddress()
7+
self.addReluctantQuant()
8+
self.addCSS()
9+
self.addNotFound()
10+
self.addGraphemeBreak()
11+
self.addHangulSyllable()
12+
// self.addHTML() // Disabled due to \b being unusably slow
13+
self.addEmail()
14+
self.addCustomCharacterClasses()
15+
self.addBuiltinCC()
16+
self.addUnicode()
17+
self.addLiteralSearch()
18+
self.addDiceNotation()
19+
self.addErrorMessages()
20+
self.addIpAddress()
2521
// -- end of registrations --
26-
return benchmark
2722
}
2823
}

0 commit comments

Comments
 (0)