]> Cypherpunks.ru repositories - gostls13.git/commitdiff
regexp/syntax: test for lowercase letters first in IsWordChar
authorLudi Rehak <ludi317@gmail.com>
Wed, 4 May 2022 22:22:21 +0000 (15:22 -0700)
committerGopher Robot <gobot@golang.org>
Tue, 14 Mar 2023 04:39:42 +0000 (04:39 +0000)
Lowercase letters occur more frequently than uppercase letters
in English text.  In IsWordChar, evaluate the most common case
(lowercase letters) first to minimize the expected value of its
execution time. Code clarity does not suffer by rearranging the
order of the checks.

Add a benchmark on a sentence demonstrating the performance
improvement.

name           old time/op  new time/op  delta
IsWordChar-10   122ns ± 0%   114ns ± 1%  -6.68%  (p=0.000 n=8+10)

Change-Id: Ieee8126a4bd8ee8703905b4f75724623029f6fa2
Reviewed-on: https://go-review.googlesource.com/c/go/+/404100
Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Run-TryBot: Ian Lance Taylor <iant@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: thepudds <thepudds1460@gmail.com>

src/regexp/syntax/prog.go
src/regexp/syntax/prog_test.go

index 896cdc42c2a4ff4bd20b2ebda1d695bb594cdae1..66995e2052de59bc6a614cd922a01db9b45d8be2 100644 (file)
@@ -106,7 +106,9 @@ func EmptyOpContext(r1, r2 rune) EmptyOp {
 // during the evaluation of the \b and \B zero-width assertions.
 // These assertions are ASCII-only: the word characters are [A-Za-z0-9_].
 func IsWordChar(r rune) bool {
-       return 'A' <= r && r <= 'Z' || 'a' <= r && r <= 'z' || '0' <= r && r <= '9' || r == '_'
+       // Test for lowercase letters first, as these occur more
+       // frequently than uppercase letters in common cases.
+       return 'a' <= r && r <= 'z' || 'A' <= r && r <= 'Z' || '0' <= r && r <= '9' || r == '_'
 }
 
 // An Inst is a single instruction in a regular expression program.
index 5603aea22898f657231ef484240c51869b7b1271..54dd1dd38d670e51a4b304b9e103e946a899c297 100644 (file)
@@ -127,3 +127,18 @@ func BenchmarkEmptyOpContext(b *testing.B) {
                EmptyOpContext(r1, -1)
        }
 }
+
+var sink any
+
+func BenchmarkIsWordChar(b *testing.B) {
+       const chars = "Don't communicate by sharing memory, share memory by communicating."
+       for i := 0; i < b.N; i++ {
+               for _, r := range chars {
+                       sink = IsWordChar(r)
+               }
+       }
+       if sink == nil {
+               b.Fatal("Benchmark did not run")
+       }
+       sink = nil
+}