Commit 382c461a authored by Rui Ueyama's avatar Rui Ueyama

strings: speed up byteReplacer.Replace

benchmark                         old ns/op    new ns/op    delta
BenchmarkByteReplacerWriteString       7359         3661  -50.25%

LGTM=dave
R=golang-codereviews, dave
CC=golang-codereviews
https://golang.org/cl/102550043
parent 22d46d53
...@@ -53,6 +53,9 @@ func NewReplacer(oldnew ...string) *Replacer { ...@@ -53,6 +53,9 @@ func NewReplacer(oldnew ...string) *Replacer {
if allNewBytes { if allNewBytes {
bb := &byteReplacer{} bb := &byteReplacer{}
for i := range bb.new {
bb.new[i] = byte(i)
}
for i := 0; i < len(oldnew); i += 2 { for i := 0; i < len(oldnew); i += 2 {
o, n := oldnew[i][0], oldnew[i+1][0] o, n := oldnew[i][0], oldnew[i+1][0]
if bb.old.isSet(o) { if bb.old.isSet(o) {
...@@ -426,8 +429,8 @@ type byteReplacer struct { ...@@ -426,8 +429,8 @@ type byteReplacer struct {
// old has a bit set for each old byte that should be replaced. // old has a bit set for each old byte that should be replaced.
old byteBitmap old byteBitmap
// replacement byte, indexed by old byte. only valid if // replacement byte, indexed by old byte. old byte and new
// corresponding old bit is set. // byte are the same if corresponding old bit is not set.
new [256]byte new [256]byte
} }
...@@ -460,10 +463,8 @@ func (r *byteReplacer) WriteString(w io.Writer, s string) (n int, err error) { ...@@ -460,10 +463,8 @@ func (r *byteReplacer) WriteString(w io.Writer, s string) (n int, err error) {
ncopy := copy(buf, s[:]) ncopy := copy(buf, s[:])
s = s[ncopy:] s = s[ncopy:]
for i, b := range buf[:ncopy] { for i, b := range buf[:ncopy] {
if r.old.isSet(b) {
buf[i] = r.new[b] buf[i] = r.new[b]
} }
}
wn, err := w.Write(buf[:ncopy]) wn, err := w.Write(buf[:ncopy])
n += wn n += wn
if err != nil { if err != nil {
......
...@@ -480,7 +480,7 @@ func BenchmarkHTMLEscapeOld(b *testing.B) { ...@@ -480,7 +480,7 @@ func BenchmarkHTMLEscapeOld(b *testing.B) {
} }
} }
func BenchmarkWriteString(b *testing.B) { func BenchmarkByteStringReplacerWriteString(b *testing.B) {
str := Repeat("I <3 to escape HTML & other text too.", 100) str := Repeat("I <3 to escape HTML & other text too.", 100)
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
...@@ -489,6 +489,15 @@ func BenchmarkWriteString(b *testing.B) { ...@@ -489,6 +489,15 @@ func BenchmarkWriteString(b *testing.B) {
} }
} }
func BenchmarkByteReplacerWriteString(b *testing.B) {
str := Repeat("abcdefghijklmnopqrstuvwxyz", 100)
buf := new(bytes.Buffer)
for i := 0; i < b.N; i++ {
capitalLetters.WriteString(buf, str)
buf.Reset()
}
}
// BenchmarkByteByteReplaces compares byteByteImpl against multiple Replaces. // BenchmarkByteByteReplaces compares byteByteImpl against multiple Replaces.
func BenchmarkByteByteReplaces(b *testing.B) { func BenchmarkByteByteReplaces(b *testing.B) {
str := Repeat("a", 100) + Repeat("b", 100) str := Repeat("a", 100) + Repeat("b", 100)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment