@@ -4,12 +4,11 @@ import Foundation
4
4
public protocol RegexBenchmark {
5
5
var name : String { get }
6
6
func run( )
7
- func debug( )
8
7
}
9
8
10
9
public struct Benchmark : RegexBenchmark {
11
10
public let name : String
12
- let regex : Regex < AnyRegexOutput >
11
+ let regex : Regex < Substring >
13
12
let type : MatchType
14
13
let target : String
15
14
@@ -51,6 +50,66 @@ public struct NSBenchmark: RegexBenchmark {
51
50
}
52
51
}
53
52
53
+ public struct BenchmarkRunner {
54
+ // Register instances of Benchmark and run them
55
+ let suiteName : String
56
+ var suite : [ any RegexBenchmark ]
57
+ let samples : Int
58
+
59
+ public init ( _ suiteName: String ) {
60
+ self . suiteName = suiteName
61
+ self . suite = [ ]
62
+ self . samples = 20
63
+ }
64
+
65
+ public init ( _ suiteName: String , _ n: Int ) {
66
+ self . suiteName = suiteName
67
+ self . suite = [ ]
68
+ self . samples = n
69
+ }
70
+
71
+ public mutating func register( _ new: some RegexBenchmark ) {
72
+ suite. append ( new)
73
+ }
74
+
75
+ func measure( benchmark: some RegexBenchmark ) -> Time {
76
+ var times : [ Time ] = [ ]
77
+
78
+ // initial run to make sure the regex has been compiled
79
+ benchmark. run ( )
80
+
81
+ // fixme: use suspendingclock?
82
+ for _ in 0 ..< samples {
83
+ let start = Tick . now
84
+ benchmark. run ( )
85
+ let end = Tick . now
86
+ let time = end. elapsedTime ( since: start)
87
+ times. append ( time)
88
+ }
89
+ // todo: compute stdev and warn if it's too large
90
+
91
+ // return median time
92
+ times. sort ( )
93
+ return times [ samples/ 2 ]
94
+ }
95
+
96
+ public func run( ) {
97
+ print ( " Running " )
98
+ for b in suite {
99
+ print ( " - \( b. name) \( measure ( benchmark: b) ) " )
100
+ }
101
+ }
102
+
103
+ public func profile( ) {
104
+ print ( " Starting " )
105
+ for b in suite {
106
+ print ( " - \( b. name) " )
107
+ b. run ( )
108
+ print ( " - done " )
109
+ }
110
+ }
111
+ }
112
+
54
113
/// A benchmark meant to be ran across multiple engines
55
114
struct CrossBenchmark {
56
115
/// The base name of the benchmark
@@ -71,7 +130,7 @@ struct CrossBenchmark {
71
130
var isWhole : Bool = false
72
131
73
132
func register( _ runner: inout BenchmarkRunner ) {
74
- let swiftRegex = try ! Regex ( regex)
133
+ let swiftRegex = try ! Regex ( regex, as : Substring . self )
75
134
76
135
let nsPattern = isWhole ? " ^ " + regex + " $ " : regex
77
136
let nsRegex : NSRegularExpression
0 commit comments