@@ -4,12 +4,11 @@ import Foundation
44public protocol RegexBenchmark {
55 var name : String { get }
66 func run( )
7- func debug( )
87}
98
109public struct Benchmark : RegexBenchmark {
1110 public let name : String
12- let regex : Regex < AnyRegexOutput >
11+ let regex : Regex < Substring >
1312 let type : MatchType
1413 let target : String
1514
@@ -51,6 +50,66 @@ public struct NSBenchmark: RegexBenchmark {
5150 }
5251}
5352
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+
54113/// A benchmark meant to be ran across multiple engines
55114struct CrossBenchmark {
56115 /// The base name of the benchmark
@@ -71,7 +130,7 @@ struct CrossBenchmark {
71130 var isWhole : Bool = false
72131
73132 func register( _ runner: inout BenchmarkRunner ) {
74- let swiftRegex = try ! Regex ( regex)
133+ let swiftRegex = try ! Regex ( regex, as : Substring . self )
75134
76135 let nsPattern = isWhole ? " ^ " + regex + " $ " : regex
77136 let nsRegex : NSRegularExpression
0 commit comments