]> Cypherpunks repositories - gostls13.git/commitdiff
regexp/syntax: optimize EmptyOpContext
authorBrad Fitzpatrick <bradfitz@golang.org>
Thu, 29 Aug 2013 21:31:10 +0000 (14:31 -0700)
committerBrad Fitzpatrick <bradfitz@golang.org>
Thu, 29 Aug 2013 21:31:10 +0000 (14:31 -0700)
Minor. Saw this in a profile at few percent of CPU and was
curious what it was. Improves overall regexp benchmarks
anywhere from 0 to 3%, but they're a pain to run. You need to
run them in isolation for long runs to get stable numbers.

benchmark                  old ns/op    new ns/op    delta
BenchmarkEmptyOpContext          537          473  -11.92%

R=golang-dev, crawshaw
CC=golang-dev
https://golang.org/cl/13407043

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

index 902d3b3a57e17797cca9937a08aeb2c8c7b99719..a482a82f21545b03ffb43f690be1411475825199 100644 (file)
@@ -56,23 +56,26 @@ const (
 // Passing r2 == -1 indicates that the position is
 // at the end of the text.
 func EmptyOpContext(r1, r2 rune) EmptyOp {
-       var op EmptyOp
-       if r1 < 0 {
-               op |= EmptyBeginText | EmptyBeginLine
-       }
-       if r1 == '\n' {
+       var op EmptyOp = EmptyNoWordBoundary
+       var boundary byte
+       switch {
+       case IsWordChar(r1):
+               boundary = 1
+       case r1 == '\n':
                op |= EmptyBeginLine
+       case r1 < 0:
+               op |= EmptyBeginText | EmptyBeginLine
        }
-       if r2 < 0 {
-               op |= EmptyEndText | EmptyEndLine
-       }
-       if r2 == '\n' {
+       switch {
+       case IsWordChar(r2):
+               boundary ^= 1
+       case r2 == '\n':
                op |= EmptyEndLine
+       case r2 < 0:
+               op |= EmptyEndText | EmptyEndLine
        }
-       if IsWordChar(r1) != IsWordChar(r2) {
-               op |= EmptyWordBoundary
-       } else {
-               op |= EmptyNoWordBoundary
+       if boundary != 0 { // IsWordChar(r1) != IsWordChar(r2)
+               op ^= (EmptyWordBoundary | EmptyNoWordBoundary)
        }
        return op
 }
index 663d5a8d7788bf5b961adf48b1a461acd62f8843..cd71abc2a471cc3571041d328ac4fdd9428aaa0f 100644 (file)
@@ -103,3 +103,14 @@ func TestCompile(t *testing.T) {
                }
        }
 }
+
+func BenchmarkEmptyOpContext(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               var r1 rune = -1
+               for _, r2 := range "foo, bar, baz\nsome input text.\n" {
+                       EmptyOpContext(r1, r2)
+                       r1 = r2
+               }
+               EmptyOpContext(r1, -1)
+       }
+}