From: Alex Gaynor Date: Tue, 28 Apr 2020 01:18:29 +0000 (+0000) Subject: encoding/csv: optimize Write by giving fieldNeedsQuotes a fast path for when Comma... X-Git-Tag: go1.15beta1~224 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=d75ee813b50e1ff2fec72d501b7b77bc868a3228;p=gostls13.git encoding/csv: optimize Write by giving fieldNeedsQuotes a fast path for when Comma is ascii name old time/op new time/op delta Write-4 2.37µs ±20% 1.90µs ±19% -19.54% (p=0.015 n=6+6) Change-Id: Iadfd9a43c958704c49ceb540b44d145220f9a72f GitHub-Last-Rev: e7d8b0bd69870a24fdd800401d721e4c5bda7750 GitHub-Pull-Request: golang/go#34507 Reviewed-on: https://go-review.googlesource.com/c/go/+/197078 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- diff --git a/src/encoding/csv/writer.go b/src/encoding/csv/writer.go index 3f34bc51db..ac64b4d54c 100644 --- a/src/encoding/csv/writer.go +++ b/src/encoding/csv/writer.go @@ -158,10 +158,24 @@ func (w *Writer) fieldNeedsQuotes(field string) bool { if field == "" { return false } - if field == `\.` || strings.ContainsRune(field, w.Comma) || strings.ContainsAny(field, "\"\r\n") { + + if field == `\.` { return true } + if w.Comma < utf8.RuneSelf { + for i := 0; i < len(field); i++ { + c := field[i] + if c == '\n' || c == '\r' || c == '"' || c == byte(w.Comma) { + return true + } + } + } else { + if strings.ContainsRune(field, w.Comma) || strings.ContainsAny(field, "\"\r\n") { + return true + } + } + r1, _ := utf8.DecodeRuneInString(field) return unicode.IsSpace(r1) } diff --git a/src/encoding/csv/writer_test.go b/src/encoding/csv/writer_test.go index 011f01c172..ab28b0d7c3 100644 --- a/src/encoding/csv/writer_test.go +++ b/src/encoding/csv/writer_test.go @@ -93,3 +93,20 @@ func TestError(t *testing.T) { t.Error("Error should not be nil") } } + +var benchmarkWriteData = [][]string{ + {"abc", "def", "12356", "1234567890987654311234432141542132"}, + {"abc", "def", "12356", "1234567890987654311234432141542132"}, + {"abc", "def", "12356", "1234567890987654311234432141542132"}, +} + +func BenchmarkWrite(b *testing.B) { + for i := 0; i < b.N; i++ { + w := NewWriter(&bytes.Buffer{}) + err := w.WriteAll(benchmarkWriteData) + if err != nil { + b.Fatal(err) + } + w.Flush() + } +}