From c05e499eea19f31261b42cf97a5d5e0b0b419429 Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Thu, 16 Oct 2025 10:52:22 -0500 Subject: [PATCH] Add a 'compile-once-test' subcommand Adds a new subcommand to the RegexTester executable that demonstrates the difference between using regex patterns in different locations: - statically created - local to a function, but outside a loop - local to a function, inside a loop The compiler currently does not hoist the regex out of the loop, so it pays the parse/compile cost during every iteration. --- Sources/RegexTester/CompileOnceTest.swift | 119 ++++++++++++++++++++++ Sources/RegexTester/Main.swift | 24 +++++ Sources/RegexTester/RegexTester.swift | 7 +- 3 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 Sources/RegexTester/CompileOnceTest.swift create mode 100644 Sources/RegexTester/Main.swift diff --git a/Sources/RegexTester/CompileOnceTest.swift b/Sources/RegexTester/CompileOnceTest.swift new file mode 100644 index 000000000..56de4afd8 --- /dev/null +++ b/Sources/RegexTester/CompileOnceTest.swift @@ -0,0 +1,119 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2021-2022 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +import ArgumentParser +import _RegexParser +import _StringProcessing +import Foundation + +@available(SwiftStdlib 5.8, *) +let litPattern = #/a+bcd(?:g*)ab+?c?de(?:(?:(?i:f)))hij|zzz++a|3|2|1/# +@available(SwiftStdlib 5.8, *) +let strPattern = try! Regex("a+bcd(?:g*)ab+?c?de(?:(?:(?i:f)))hij|zzz++a|3|2|1") + +@available(SwiftStdlib 5.8, *) +struct CompileOnceTest: ParsableCommand { + static let litPattern = #/a+bcd(?:g*)ab+?c?de(?:(?:(?i:f)))hij|zzz++a|3|2|1/# + static let strPattern = try! Regex("a+bcd(?:g*)ab+?c?de(?:(?:(?i:f)))hij|zzz++a|3|2|1") + + var N: Int { 10_000 } + var testString = "zzzzzzzzza" + + func globalLitPattern() -> TimeInterval { + let start = Date.now + for _ in 0.. TimeInterval { + let start = Date.now + for _ in 0.. TimeInterval { + let start = Date.now + for _ in 0.. TimeInterval { + let start = Date.now + for _ in 0.. TimeInterval { + let start = Date.now + let pattern = #/a+bcd(?:g*)ab+?c?de(?:(?:(?i:f)))hij|zzz++a|3|2|1/# + for _ in 0.. TimeInterval { + let start = Date.now + let pattern = try! Regex("a+bcd(?:g*)ab+?c?de(?:(?:(?i:f)))hij|zzz++a|3|2|1") + for _ in 0.. TimeInterval { + let start = Date.now + for _ in 0.. TimeInterval { + let start = Date.now + for _ in 0.. Regex.Match? @Argument(help: "The regex pattern to test.")