Skip to content

Commit 03db4e2

Browse files
authored
Merge pull request #795 from milseman/update_swift_main
Update swift 6.1
2 parents ed6f29f + 35497fb commit 03db4e2

Some content is hidden

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

63 files changed

+982
-1799
lines changed

CODE_OF_CONDUCT.md

Lines changed: 0 additions & 38 deletions
This file was deleted.

CONTRIBUTING.md

Lines changed: 0 additions & 11 deletions
This file was deleted.

Package.swift

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ let package = Package(
5959
name: "VariadicsGenerator",
6060
targets: ["VariadicsGenerator"]),
6161
// Disable to work around rdar://126877024
62-
// .executable(
63-
// name: "RegexBenchmark",
64-
// targets: ["RegexBenchmark"])
62+
.executable(
63+
name: "RegexBenchmark",
64+
targets: ["RegexBenchmark"])
6565
],
6666
dependencies: [
6767
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.0.0"),
@@ -96,7 +96,7 @@ let package = Package(
9696
swiftSettings: [availabilityDefinition]),
9797
.testTarget(
9898
name: "RegexTests",
99-
dependencies: ["_StringProcessing", "TestSupport"],
99+
dependencies: ["_StringProcessing", "RegexBuilder", "TestSupport"],
100100
swiftSettings: [
101101
availabilityDefinition
102102
]),
@@ -143,17 +143,17 @@ let package = Package(
143143
"_StringProcessing"
144144
],
145145
swiftSettings: [availabilityDefinition]),
146-
// .executableTarget(
147-
// name: "RegexBenchmark",
148-
// dependencies: [
149-
// .product(name: "ArgumentParser", package: "swift-argument-parser"),
150-
// "_RegexParser",
151-
// "_StringProcessing",
152-
// "RegexBuilder"
153-
// ],
154-
// swiftSettings: [
155-
// .unsafeFlags(["-Xfrontend", "-disable-availability-checking"]),
156-
// ]),
146+
.executableTarget(
147+
name: "RegexBenchmark",
148+
dependencies: [
149+
.product(name: "ArgumentParser", package: "swift-argument-parser"),
150+
"_RegexParser",
151+
"_StringProcessing",
152+
"RegexBuilder"
153+
],
154+
swiftSettings: [
155+
.unsafeFlags(["-Xfrontend", "-disable-availability-checking"]),
156+
]),
157157

158158
// MARK: Exercises
159159
.target(

Sources/Exercises/Participants/HandWrittenParticipant.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ private func graphemeBreakPropertyData(
6060
}
6161

6262
// For testing our framework
63-
if forceFailure, lower == Unicode.Scalar(0x07FD) {
63+
let failureSigil = Unicode.Scalar(0x07FD as UInt32)!
64+
if forceFailure, lower == failureSigil {
6465
return nil
6566
}
6667

Sources/RegexBenchmark/Benchmark.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,29 +153,34 @@ struct CrossBenchmark {
153153
/// Whether to also run scalar-semantic mode
154154
var alsoRunScalarSemantic: Bool = true
155155

156+
var alsoRunSimpleWordBoundaries: Bool = false
157+
156158
func register(_ runner: inout BenchmarkRunner) {
157159
if isWhole {
158160
runner.registerCrossBenchmark(
159161
nameBase: baseName,
160162
input: input,
161163
pattern: regex,
162164
.whole,
163-
alsoRunScalarSemantic: alsoRunScalarSemantic)
165+
alsoRunScalarSemantic: alsoRunScalarSemantic,
166+
alsoRunSimpleWordBoundaries: alsoRunSimpleWordBoundaries)
164167
} else {
165168
runner.registerCrossBenchmark(
166169
nameBase: baseName,
167170
input: input,
168171
pattern: regex,
169172
.allMatches,
170-
alsoRunScalarSemantic: alsoRunScalarSemantic)
173+
alsoRunScalarSemantic: alsoRunScalarSemantic,
174+
alsoRunSimpleWordBoundaries: alsoRunSimpleWordBoundaries)
171175

172176
if includeFirst || runner.includeFirstOverride {
173177
runner.registerCrossBenchmark(
174178
nameBase: baseName,
175179
input: input,
176180
pattern: regex,
177181
.first,
178-
alsoRunScalarSemantic: alsoRunScalarSemantic)
182+
alsoRunScalarSemantic: alsoRunScalarSemantic,
183+
alsoRunSimpleWordBoundaries: alsoRunSimpleWordBoundaries)
179184
}
180185
}
181186
}

Sources/RegexBenchmark/BenchmarkRegistration.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ extension BenchmarkRunner {
1818
self.addDiceNotation()
1919
self.addErrorMessages()
2020
self.addIpAddress()
21+
22+
self.addURLWithWordBoundaries()
23+
self.addFSPathsRegex()
2124
// -- end of registrations --
2225
}
2326
}

Sources/RegexBenchmark/BenchmarkResults.swift

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,21 @@ extension BenchmarkRunner {
2121
self.results = result
2222
print("Loaded results from \(url.path)")
2323
}
24-
24+
25+
/// Attempts to save results in a CSV format to the given path
26+
func saveCSV(to savePath: String) throws {
27+
let url = URL(fileURLWithPath: savePath, isDirectory: false)
28+
let parent = url.deletingLastPathComponent()
29+
if !FileManager.default.fileExists(atPath: parent.path) {
30+
try! FileManager.default.createDirectory(
31+
atPath: parent.path,
32+
withIntermediateDirectories: true)
33+
}
34+
print("Saving result as CSV to \(url.path)")
35+
try results.saveCSV(to: url)
36+
37+
}
38+
2539
/// Compare this runner's results against the results stored in the given file path
2640
func compare(
2741
against compareFilePath: String,
@@ -153,6 +167,12 @@ struct Measurement: Codable, CustomStringConvertible {
153167
var description: String {
154168
return "\(median) (stdev: \(Time(stdev)), N = \(samples))"
155169
}
170+
171+
var asCSV: String {
172+
"""
173+
\(median.asCSVSeconds), \(stdev), \(samples)
174+
"""
175+
}
156176
}
157177

158178
struct BenchmarkResult: Codable, CustomStringConvertible {
@@ -170,6 +190,13 @@ struct BenchmarkResult: Codable, CustomStringConvertible {
170190
}
171191
return base
172192
}
193+
194+
var asCSV: String {
195+
let na = "N/A, N/A, N/A"
196+
return """
197+
\(runtime.asCSV), \(compileTime?.asCSV ?? na), \(parseTime?.asCSV ?? na)
198+
"""
199+
}
173200
}
174201

175202
extension BenchmarkResult {
@@ -263,6 +290,27 @@ struct SuiteResult {
263290
}
264291

265292
extension SuiteResult: Codable {
293+
func saveCSV(to url: URL) throws {
294+
var output: [(name: String, result: BenchmarkResult)] = []
295+
for key in results.keys {
296+
output.append((key, results[key]!))
297+
}
298+
output.sort {
299+
$0.name < $1.name
300+
}
301+
var contents = """
302+
name,\
303+
runtime_median, runTime_stddev, runTime_samples,\
304+
compileTime_median, compileTime_stddev, compileTime_samples,\
305+
parseTime_median, parseTime_stddev, parseTime_samples\n
306+
"""
307+
for (name, result) in output {
308+
contents.append("\(name), \(result.asCSV))\n")
309+
}
310+
print("Saving result as .csv to \(url.path())")
311+
try contents.write(to: url, atomically: true, encoding: String.Encoding.utf8)
312+
}
313+
266314
func save(to url: URL) throws {
267315
let encoder = JSONEncoder()
268316
let data = try encoder.encode(self)

Sources/RegexBenchmark/BenchmarkRunner.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ struct BenchmarkRunner {
3333
input: String,
3434
pattern: String,
3535
_ type: Benchmark.MatchType,
36-
alsoRunScalarSemantic: Bool = true
36+
alsoRunScalarSemantic: Bool = true,
37+
alsoRunSimpleWordBoundaries: Bool
3738
) {
3839
let swiftRegex = try! Regex(pattern)
3940
let nsRegex: NSRegularExpression
@@ -58,6 +59,16 @@ struct BenchmarkRunner {
5859
type: .init(type),
5960
target: input))
6061

62+
if alsoRunSimpleWordBoundaries {
63+
register(
64+
Benchmark(
65+
name: nameBase + nameSuffix + "_SimpleWordBoundaries",
66+
regex: swiftRegex.wordBoundaryKind(.simple),
67+
pattern: pattern,
68+
type: type,
69+
target: input))
70+
}
71+
6172
if alsoRunScalarSemantic {
6273
register(
6374
Benchmark(

Sources/RegexBenchmark/CLI.swift

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,18 @@ struct Runner: ParsableCommand {
3232
@Option(help: "Save comparison results as csv")
3333
var saveComparison: String?
3434

35+
@Option(help: "Save benchmark results as csv")
36+
var saveCSV: String?
37+
3538
@Flag(help: "Quiet mode")
3639
var quiet = false
3740

3841
@Flag(help: "Exclude running NSRegex benchmarks")
3942
var excludeNs = false
40-
43+
44+
@Flag(help: "Rather than specify specific-benchmarks as patterns, use exact names")
45+
var exactName = false
46+
4147
@Flag(help: """
4248
Enable tracing of the engine (warning: lots of output). Prints out processor state each cycle
4349
@@ -73,7 +79,11 @@ swift build -c release -Xswiftc -DPROCESSOR_MEASUREMENTS_ENABLED
7379
if !self.specificBenchmarks.isEmpty {
7480
runner.suite = runner.suite.filter { b in
7581
specificBenchmarks.contains { pattern in
76-
try! Regex(pattern).firstMatch(in: b.name) != nil
82+
if exactName {
83+
return pattern == b.name
84+
}
85+
86+
return try! Regex(pattern).firstMatch(in: b.name) != nil
7787
}
7888
}
7989
}
@@ -84,9 +94,14 @@ swift build -c release -Xswiftc -DPROCESSOR_MEASUREMENTS_ENABLED
8494

8595
if let loadFile = load {
8696
try runner.load(from: loadFile)
97+
if excludeNs {
98+
runner.results.results = runner.results.results.filter {
99+
!$0.key.contains("_NS")
100+
}
101+
}
87102
} else {
88103
if excludeNs {
89-
runner.suite = runner.suite.filter { b in !b.name.contains("NS") }
104+
runner.suite = runner.suite.filter { b in !b.name.contains("_NS") }
90105
}
91106
runner.run()
92107
}
@@ -109,5 +124,8 @@ swift build -c release -Xswiftc -DPROCESSOR_MEASUREMENTS_ENABLED
109124
if let compareFile = compareCompileTime {
110125
try runner.compareCompileTimes(against: compareFile, showChart: showChart)
111126
}
127+
if let csvPath = saveCSV {
128+
try runner.saveCSV(to: csvPath)
129+
}
112130
}
113131
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Successful match FSPaths
2+
private let pathSuccess = #"""
3+
./First/Second/Third/some/really/long/content.extension/more/stuff/OptionLeft
4+
./First/Second/Third/some/really/long/content.extension/more/stuff/OptionRight
5+
./First/Second/PrefixThird/some/really/long/content.extension/more/stuff/OptionLeft
6+
./First/Second/PrefixThird/some/really/long/content.extension/more/stuff/OptionRight
7+
"""#
8+
9+
// Unsucessful match FSPaths.
10+
//
11+
// We will have far more failures than successful matches by interspersing
12+
// this whole list between each success
13+
private let pathFailure = #"""
14+
a/b/c
15+
/smol/path
16+
/a/really/long/path/that/is/certainly/stored/out/of/line
17+
./First/Second/Third/some/really/long/content.extension/more/stuff/NothingToSeeHere
18+
./First/Second/PrefixThird/some/really/long/content.extension/more/stuff/NothingToSeeHere
19+
./First/Second/Third/some/really/long/content.extension/more/stuff/OptionNeither
20+
./First/Second/PrefixThird/some/really/long/content.extension/more/stuff/OptionNeither
21+
/First/Second/Third/some/really/long/content.extension/more/stuff/OptionLeft
22+
/First/Second/Third/some/really/long/content.extension/more/stuff/OptionRight
23+
/First/Second/PrefixThird/some/really/long/content.extension/more/stuff/OptionLeft
24+
/First/Second/PrefixThird/some/really/long/content.extension/more/stuff/OptionRight
25+
./First/Second/Third/some/really/long/content/more/stuff/OptionLeft
26+
./First/Second/Third/some/really/long/content/more/stuff/OptionRight
27+
./First/Second/PrefixThird/some/really/long/content/more/stuff/OptionLeft
28+
./First/Second/PrefixThird/some/really/long/content/more/stuff/OptionRight
29+
"""#
30+
31+
private func listify(_ s: String) -> [String] {
32+
s.split(whereSeparator: { $0.isNewline }).map { String($0) }
33+
}
34+
35+
private let pathSuccessList: [String] = { listify(pathSuccess) }()
36+
private let pathFailureList: [String] = { listify(pathFailure) }()
37+
38+
private func scale(_ input: [String]) -> [String] {
39+
let threshold = 1_000
40+
var result = input
41+
while result.count < threshold {
42+
result.append(contentsOf: input)
43+
}
44+
return result
45+
}
46+
47+
extension Inputs {
48+
static let fsPathsList: [String] = {
49+
var result = pathFailureList
50+
result.append(contentsOf: pathFailureList)
51+
52+
for success in pathSuccessList {
53+
result.append(String(success))
54+
result.append(contentsOf: pathFailureList)
55+
result.append(contentsOf: pathFailureList)
56+
}
57+
58+
// Scale result up a bit
59+
return scale(result)
60+
61+
}()
62+
63+
static let fsPathsNotFoundList: [String] = {
64+
scale(pathFailureList)
65+
}()
66+
67+
static let fsPathsFoundList: [String] = {
68+
scale(pathFailureList)
69+
}()
70+
}

0 commit comments

Comments
 (0)