encoding/csv: avoid allocations when reading records
encoding/csv: avoid allocations when reading records

This commit changes parseRecord to allocate a single string per record,
instead of per field, by using indexes into the raw record.

Benchstat (done with f69991c17)

name                          old time/op    new time/op    delta
Read-8                          3.17µs ± 0%    2.78µs ± 1%  -12.35%  (p=0.016 n=4+5)
ReadWithFieldsPerRecord-8       3.18µs ± 1%    2.79µs ± 1%  -12.23%  (p=0.008 n=5+5)
ReadWithoutFieldsPerRecord-8    4.59µs ± 0%    2.77µs ± 0%  -39.58%  (p=0.016 n=4+5)
ReadLargeFields-8               57.0µs ± 0%    55.7µs ± 0%   -2.18%  (p=0.008 n=5+5)

name                          old alloc/op   new alloc/op   delta
Read-8                            660B ± 0%      664B ± 0%   +0.61%  (p=0.008 n=5+5)
ReadWithFieldsPerRecord-8         660B ± 0%      664B ± 0%   +0.61%  (p=0.008 n=5+5)
ReadWithoutFieldsPerRecord-8    1.14kB ± 0%    0.66kB ± 0%  -41.75%  (p=0.008 n=5+5)
ReadLargeFields-8               3.86kB ± 0%    3.94kB ± 0%   +1.86%  (p=0.008 n=5+5)

name                          old allocs/op  new allocs/op  delta
Read-8                            30.0 ± 0%      18.0 ± 0%  -40.00%  (p=0.008 n=5+5)
ReadWithFieldsPerRecord-8         30.0 ± 0%      18.0 ± 0%  -40.00%  (p=0.008 n=5+5)
ReadWithoutFieldsPerRecord-8      50.0 ± 0%      18.0 ± 0%  -64.00%  (p=0.008 n=5+5)
ReadLargeFields-8                 66.0 ± 0%      24.0 ± 0%  -63.64%  (p=0.008 n=5+5)

For a simple application that I wrote, which reads in a CSV file (via
ReadAll) and outputs the number of rows read (15857625 rows), this change
reduces the total time on my notebook from ~58 seconds to ~48 seconds.

This reduces time and allocations (bytes) each by ~6% for a real world
CSV file at work (~230000 rows, 13 colums).

Updates #16791

Change-Id: Ia07177c94624e55cdd3064a7d2751fb69322d3e4
Reviewed-on: https://go-review.googlesource.com/24723
Reviewed-by: Brad Fitzpatrick <ae9783c0b0efc69cd85ab025ddd17aa44cdc4aa5@golang.org>
Run-TryBot: Brad Fitzpatrick <ae9783c0b0efc69cd85ab025ddd17aa44cdc4aa5@golang.org>
TryBot-Result: Gobot Gobot <66cb808b70d30c07676d5e946fee83fd561249e5@golang.org>

nawawi/go,ImJasonH/go,polyverse-security/go,golang/go,Cofyc/go,Cofyc/go,vsekhar/elastic-go,momchil-velikov/go,goodlang/good,polyverse-security/go,nawawi/go,cloudflare/go,suncycheng/go,Cofyc/go,Cofyc/go,suncycheng/go,Cofyc/go,vsekhar/elastic-go,suncycheng/go,akutz/go,ImJasonH/go,ImJasonH/go,josharian/go,momchil-velikov/go,polyverse-security/go,golang/go,akutz/go,nawawi/go,nawawi/go,derekmarcotte/go,nawawi/go,cloudflare/go,ImJasonH/go,vsekhar/elastic-go,linux-on-ibm-z/go,Cofyc/go,goodlang/good,linux-on-ibm-z/go,golang/go,golang/go,momchil-velikov/go,codestation/go,ImJasonH/go,akutz/go,akutz/go,CAFxX/go,akutz/go,CAFxX/go,cloudflare/go,vsekhar/elastic-go,polyverse-security/go,polyverse-security/go,derekmarcotte/go,suncycheng/go,derekmarcotte/go,derekmarcotte/go,josharian/go,cloudflare/go,goodlang/good,christopher-henderson/Go,polyverse-security/go,CAFxX/go,golang/go,codestation/go,Cofyc/go,ImJasonH/go,CAFxX/go,CAFxX/go,goodlang/good,ImJasonH/go,momchil-velikov/go,CAFxX/go,suncycheng/go,linux-on-ibm-z/go,momchil-velikov/go,derekmarcotte/go,josharian/go,nawawi/go,vsekhar/elastic-go,suncycheng/go,goodlang/good,josharian/go,ImJasonH/go,CAFxX/go,codestation/go,goodlang/good,josharian/go,nawawi/go,codestation/go,codestation/go,akutz/go,linux-on-ibm-z/go,cloudflare/go,linux-on-ibm-z/go,goodlang/good,josharian/go,suncycheng/go,CAFxX/go,josharian/go,cloudflare/go,golang/go,vsekhar/elastic-go,linux-on-ibm-z/go,Cofyc/go,akutz/go,momchil-velikov/go,golang/go,goodlang/good,golang/go,codestation/go,polyverse-security/go,derekmarcotte/go,josharian/go,cloudflare/go,codestation/go,momchil-velikov/go,linux-on-ibm-z/go,codestation/go,derekmarcotte/go,momchil-velikov/go,suncycheng/go,vsekhar/elastic-go,derekmarcotte/go,polyverse-security/go,nawawi/go,cloudflare/go,vsekhar/elastic-go,akutz/go,linux-on-ibm-z/go