mirror of
https://github.com/golang/go
synced 2024-11-18 09:54:57 -07:00
regexp: avoid alloc in QuoteMeta when not quoting
Many users quote literals in regular expressions just in case. No need to allocate then. Note: Also added benchmarks for quoting and not quoting. name old time/op new time/op delta QuoteMetaAll-4 629ns ± 6% 654ns ± 5% +4.01% (p=0.001 n=20+19) QuoteMetaNone-4 1.02µs ± 6% 0.20µs ± 0% -80.73% (p=0.000 n=18+20) name old speed new speed delta QuoteMetaAll-4 22.3MB/s ± 6% 21.4MB/s ± 5% -3.94% (p=0.001 n=20+19) QuoteMetaNone-4 25.3MB/s ± 3% 131.5MB/s ± 0% +419.28% (p=0.000 n=17+19) name old alloc/op new alloc/op delta QuoteMetaAll-4 64.0B ± 0% 64.0B ± 0% ~ (all samples are equal) QuoteMetaNone-4 96.0B ± 0% 0.0B ±NaN% -100.00% (p=0.000 n=20+20) name old allocs/op new allocs/op delta QuoteMetaAll-4 2.00 ± 0% 2.00 ± 0% ~ (all samples are equal) QuoteMetaNone-4 2.00 ± 0% 0.00 ±NaN% -100.00% (p=0.000 n=20+20) Change-Id: I38d50f463cde463115d22534f8eb849e54d899af Reviewed-on: https://go-review.googlesource.com/31395 Reviewed-by: Russ Cox <rsc@golang.org> Reviewed-by: Austin Clements <austin@google.com> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
f36e1adaa2
commit
9aed16e96d
@ -818,3 +818,23 @@ func BenchmarkMatchParallelCopied(b *testing.B) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var sink string
|
||||
|
||||
func BenchmarkQuoteMetaAll(b *testing.B) {
|
||||
s := string(specialBytes)
|
||||
b.SetBytes(int64(len(s)))
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
sink = QuoteMeta(s)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkQuoteMetaNone(b *testing.B) {
|
||||
s := "abcdefghijklmnopqrstuvwxyz"
|
||||
b.SetBytes(int64(len(s)))
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
sink = QuoteMeta(s)
|
||||
}
|
||||
}
|
||||
|
@ -600,11 +600,22 @@ func special(b byte) bool {
|
||||
// inside the argument text; the returned string is a regular expression matching
|
||||
// the literal text. For example, QuoteMeta(`[foo]`) returns `\[foo\]`.
|
||||
func QuoteMeta(s string) string {
|
||||
b := make([]byte, 2*len(s))
|
||||
|
||||
// A byte loop is correct because all metacharacters are ASCII.
|
||||
j := 0
|
||||
for i := 0; i < len(s); i++ {
|
||||
var i int
|
||||
for i = 0; i < len(s); i++ {
|
||||
if special(s[i]) {
|
||||
break
|
||||
}
|
||||
}
|
||||
// No meta characters found, so return original string.
|
||||
if i >= len(s) {
|
||||
return s
|
||||
}
|
||||
|
||||
b := make([]byte, 2*len(s)-i)
|
||||
copy(b, s[:i])
|
||||
j := i
|
||||
for ; i < len(s); i++ {
|
||||
if special(s[i]) {
|
||||
b[j] = '\\'
|
||||
j++
|
||||
@ -612,7 +623,7 @@ func QuoteMeta(s string) string {
|
||||
b[j] = s[i]
|
||||
j++
|
||||
}
|
||||
return string(b[0:j])
|
||||
return string(b[:j])
|
||||
}
|
||||
|
||||
// The number of capture values in the program may correspond
|
||||
|
Loading…
Reference in New Issue
Block a user