aboutsummaryrefslogtreecommitdiff
path: root/src/encoding/csv
diff options
context:
space:
mode:
authorJustin Nuß <nuss.justin@gmail.com>2015-04-13 20:13:14 +0200
committerBrad Fitzpatrick <bradfitz@golang.org>2015-04-26 16:28:51 +0000
commit2db58f8f2daea1c6f6134584f7811bb229177b28 (patch)
treec51049b2c0e3d213d961e8e7c9724bdc32df9012 /src/encoding/csv
parenta5b693b431d0612b97a8978fdfa7d12310d95b6f (diff)
downloadgo-2db58f8f2daea1c6f6134584f7811bb229177b28.tar.gz
go-2db58f8f2daea1c6f6134584f7811bb229177b28.zip
encoding/csv: Preallocate records slice
Currently parseRecord will always start with a nil slice and then resize the slice on append. For input with a fixed number of fields per record we can preallocate the slice to avoid having to resize the slice. This change implements this optimization by using FieldsPerRecord as capacity if it's > 0 and also adds a benchmark to better show the differences. benchmark old ns/op new ns/op delta BenchmarkRead 19741 17909 -9.28% benchmark old allocs new allocs delta BenchmarkRead 59 41 -30.51% benchmark old bytes new bytes delta BenchmarkRead 6276 5844 -6.88% Change-Id: I7c2abc9c80a23571369bcfcc99a8ffc474eae7ab Reviewed-on: https://go-review.googlesource.com/8880 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/encoding/csv')
-rw-r--r--src/encoding/csv/reader.go6
-rw-r--r--src/encoding/csv/reader_test.go22
2 files changed, 28 insertions, 0 deletions
diff --git a/src/encoding/csv/reader.go b/src/encoding/csv/reader.go
index d9432954ac..d0a09044fb 100644
--- a/src/encoding/csv/reader.go
+++ b/src/encoding/csv/reader.go
@@ -228,6 +228,12 @@ func (r *Reader) parseRecord() (fields []string, err error) {
}
r.r.UnreadRune()
+ // If FieldsPerRecord is greater then 0 we can assume the final
+ // length of fields to be equal to FieldsPerRecord.
+ if r.FieldsPerRecord > 0 {
+ fields = make([]string, 0, r.FieldsPerRecord)
+ }
+
// At this point we have at least one field.
for {
haveField, delim, err := r.parseField()
diff --git a/src/encoding/csv/reader_test.go b/src/encoding/csv/reader_test.go
index 123df06bc8..b3c4f3bf18 100644
--- a/src/encoding/csv/reader_test.go
+++ b/src/encoding/csv/reader_test.go
@@ -282,3 +282,25 @@ func TestRead(t *testing.T) {
}
}
}
+
+func BenchmarkRead(b *testing.B) {
+ data := `x,y,z,w
+x,y,z,
+x,y,,
+x,,,
+,,,
+"x","y","z","w"
+"x","y","z",""
+"x","y","",""
+"x","","",""
+"","","",""
+`
+
+ for i := 0; i < b.N; i++ {
+ _, err := NewReader(strings.NewReader(data)).ReadAll()
+
+ if err != nil {
+ b.Fatalf("could not read data: %s", err)
+ }
+ }
+}