Skip to content

Commit df5997b

Browse files
josharianbradfitz
authored andcommitted
regexp: don't allocate when All methods find no matches
name old time/op new time/op delta FindAllNoMatches-8 216ns ± 3% 122ns ± 2% -43.52% (p=0.000 n=10+10) name old alloc/op new alloc/op delta FindAllNoMatches-8 240B ± 0% 0B -100.00% (p=0.000 n=10+10) name old allocs/op new allocs/op delta FindAllNoMatches-8 1.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) This work was supported by Sourcegraph. Change-Id: I30aac201370ccfb40a6ff637402020ac20f61f70 Reviewed-on: https://go-review.googlesource.com/87418 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Reviewed-by: Daniel Martí <mvdan@mvdan.cc> TryBot-Result: Gobot Gobot <gobot@golang.org>
1 parent 4b8a7ea commit df5997b

File tree

2 files changed

+45
-32
lines changed

2 files changed

+45
-32
lines changed

src/regexp/all_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,19 @@ func BenchmarkFind(b *testing.B) {
581581
}
582582
}
583583

584+
func BenchmarkFindAllNoMatches(b *testing.B) {
585+
re := MustCompile("a+b+")
586+
s := []byte("acddee")
587+
b.ReportAllocs()
588+
b.ResetTimer()
589+
for i := 0; i < b.N; i++ {
590+
all := re.FindAll(s, -1)
591+
if all != nil {
592+
b.Fatalf("FindAll(%q) = %q; want nil", s, all)
593+
}
594+
}
595+
}
596+
584597
func BenchmarkFindString(b *testing.B) {
585598
b.StopTimer()
586599
re := MustCompile("a+b+")

src/regexp/regexp.go

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -984,13 +984,13 @@ func (re *Regexp) FindAll(b []byte, n int) [][]byte {
984984
if n < 0 {
985985
n = len(b) + 1
986986
}
987-
result := make([][]byte, 0, startSize)
987+
var result [][]byte
988988
re.allMatches("", b, n, func(match []int) {
989+
if result == nil {
990+
result = make([][]byte, 0, startSize)
991+
}
989992
result = append(result, b[match[0]:match[1]])
990993
})
991-
if len(result) == 0 {
992-
return nil
993-
}
994994
return result
995995
}
996996

@@ -1002,13 +1002,13 @@ func (re *Regexp) FindAllIndex(b []byte, n int) [][]int {
10021002
if n < 0 {
10031003
n = len(b) + 1
10041004
}
1005-
result := make([][]int, 0, startSize)
1005+
var result [][]int
10061006
re.allMatches("", b, n, func(match []int) {
1007+
if result == nil {
1008+
result = make([][]int, 0, startSize)
1009+
}
10071010
result = append(result, match[0:2])
10081011
})
1009-
if len(result) == 0 {
1010-
return nil
1011-
}
10121012
return result
10131013
}
10141014

@@ -1020,13 +1020,13 @@ func (re *Regexp) FindAllString(s string, n int) []string {
10201020
if n < 0 {
10211021
n = len(s) + 1
10221022
}
1023-
result := make([]string, 0, startSize)
1023+
var result []string
10241024
re.allMatches(s, nil, n, func(match []int) {
1025+
if result == nil {
1026+
result = make([]string, 0, startSize)
1027+
}
10251028
result = append(result, s[match[0]:match[1]])
10261029
})
1027-
if len(result) == 0 {
1028-
return nil
1029-
}
10301030
return result
10311031
}
10321032

@@ -1038,13 +1038,13 @@ func (re *Regexp) FindAllStringIndex(s string, n int) [][]int {
10381038
if n < 0 {
10391039
n = len(s) + 1
10401040
}
1041-
result := make([][]int, 0, startSize)
1041+
var result [][]int
10421042
re.allMatches(s, nil, n, func(match []int) {
1043+
if result == nil {
1044+
result = make([][]int, 0, startSize)
1045+
}
10431046
result = append(result, match[0:2])
10441047
})
1045-
if len(result) == 0 {
1046-
return nil
1047-
}
10481048
return result
10491049
}
10501050

@@ -1056,8 +1056,11 @@ func (re *Regexp) FindAllSubmatch(b []byte, n int) [][][]byte {
10561056
if n < 0 {
10571057
n = len(b) + 1
10581058
}
1059-
result := make([][][]byte, 0, startSize)
1059+
var result [][][]byte
10601060
re.allMatches("", b, n, func(match []int) {
1061+
if result == nil {
1062+
result = make([][][]byte, 0, startSize)
1063+
}
10611064
slice := make([][]byte, len(match)/2)
10621065
for j := range slice {
10631066
if match[2*j] >= 0 {
@@ -1066,9 +1069,6 @@ func (re *Regexp) FindAllSubmatch(b []byte, n int) [][][]byte {
10661069
}
10671070
result = append(result, slice)
10681071
})
1069-
if len(result) == 0 {
1070-
return nil
1071-
}
10721072
return result
10731073
}
10741074

@@ -1080,13 +1080,13 @@ func (re *Regexp) FindAllSubmatchIndex(b []byte, n int) [][]int {
10801080
if n < 0 {
10811081
n = len(b) + 1
10821082
}
1083-
result := make([][]int, 0, startSize)
1083+
var result [][]int
10841084
re.allMatches("", b, n, func(match []int) {
1085+
if result == nil {
1086+
result = make([][]int, 0, startSize)
1087+
}
10851088
result = append(result, match)
10861089
})
1087-
if len(result) == 0 {
1088-
return nil
1089-
}
10901090
return result
10911091
}
10921092

@@ -1098,8 +1098,11 @@ func (re *Regexp) FindAllStringSubmatch(s string, n int) [][]string {
10981098
if n < 0 {
10991099
n = len(s) + 1
11001100
}
1101-
result := make([][]string, 0, startSize)
1101+
var result [][]string
11021102
re.allMatches(s, nil, n, func(match []int) {
1103+
if result == nil {
1104+
result = make([][]string, 0, startSize)
1105+
}
11031106
slice := make([]string, len(match)/2)
11041107
for j := range slice {
11051108
if match[2*j] >= 0 {
@@ -1108,9 +1111,6 @@ func (re *Regexp) FindAllStringSubmatch(s string, n int) [][]string {
11081111
}
11091112
result = append(result, slice)
11101113
})
1111-
if len(result) == 0 {
1112-
return nil
1113-
}
11141114
return result
11151115
}
11161116

@@ -1123,13 +1123,13 @@ func (re *Regexp) FindAllStringSubmatchIndex(s string, n int) [][]int {
11231123
if n < 0 {
11241124
n = len(s) + 1
11251125
}
1126-
result := make([][]int, 0, startSize)
1126+
var result [][]int
11271127
re.allMatches(s, nil, n, func(match []int) {
1128+
if result == nil {
1129+
result = make([][]int, 0, startSize)
1130+
}
11281131
result = append(result, match)
11291132
})
1130-
if len(result) == 0 {
1131-
return nil
1132-
}
11331133
return result
11341134
}
11351135

0 commit comments

Comments
 (0)