diff options
author | Justin Nuß <nuss.justin@gmail.com> | 2015-04-13 20:13:14 +0200 |
---|---|---|
committer | Brad Fitzpatrick <bradfitz@golang.org> | 2015-04-26 16:28:51 +0000 |
commit | 2db58f8f2daea1c6f6134584f7811bb229177b28 (patch) | |
tree | c51049b2c0e3d213d961e8e7c9724bdc32df9012 /src/encoding/csv | |
parent | a5b693b431d0612b97a8978fdfa7d12310d95b6f (diff) | |
download | go-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.go | 6 | ||||
-rw-r--r-- | src/encoding/csv/reader_test.go | 22 |
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) + } + } +} |