]> Cypherpunks repositories - gostls13.git/commitdiff
strings: speed up byteReplacer.Replace
authorRui Ueyama <ruiu@google.com>
Fri, 20 Jun 2014 19:18:33 +0000 (12:18 -0700)
committerRui Ueyama <ruiu@google.com>
Fri, 20 Jun 2014 19:18:33 +0000 (12:18 -0700)
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

src/pkg/strings/replace.go
src/pkg/strings/replace_test.go

index 03fb6b249d649ce19ade31429decf03a182c8f0d..cb9d7b1fa45b62fe9a42c57a4b82cdafef5fa952 100644 (file)
@@ -53,6 +53,9 @@ func NewReplacer(oldnew ...string) *Replacer {
 
        if allNewBytes {
                bb := &byteReplacer{}
+               for i := range bb.new {
+                       bb.new[i] = byte(i)
+               }
                for i := 0; i < len(oldnew); i += 2 {
                        o, n := oldnew[i][0], oldnew[i+1][0]
                        if bb.old.isSet(o) {
@@ -426,8 +429,8 @@ type byteReplacer struct {
        // old has a bit set for each old byte that should be replaced.
        old byteBitmap
 
-       // replacement byte, indexed by old byte. only valid if
-       // corresponding old bit is set.
+       // replacement byte, indexed by old byte. old byte and new
+       // byte are the same if corresponding old bit is not set.
        new [256]byte
 }
 
@@ -460,9 +463,7 @@ func (r *byteReplacer) WriteString(w io.Writer, s string) (n int, err error) {
                ncopy := copy(buf, s[:])
                s = s[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])
                n += wn
index ca57f08251ef9e30dfc688df61f4b81b9d2e4154..2cb318b69d7e25884ac41788a48385c0b669c5f3 100644 (file)
@@ -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)
        buf := new(bytes.Buffer)
        for i := 0; i < b.N; i++ {
@@ -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.
 func BenchmarkByteByteReplaces(b *testing.B) {
        str := Repeat("a", 100) + Repeat("b", 100)