Created
September 13, 2019 11:44
-
-
Save KalleDK/6616d6634a787fa31cfff02c47110f2c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package csvutil_test | |
import ( | |
"bytes" | |
"encoding/csv" | |
"testing" | |
"io" | |
"time" | |
"github.com/jszwec/csvutil" | |
csvutildk "github.com/KalleDK/csvutil" | |
) | |
type A struct { | |
A int `csv:"a" name:"a"` | |
B float64 `csv:"b" name:"b"` | |
C string `csv:"c" name:"c"` | |
D int64 `csv:"d" name:"d"` | |
E int8 `csv:"e" name:"e"` | |
F float32 `csv:"f" name:"f"` | |
G float32 `csv:"g" name:"g"` | |
H float32 `csv:"h" name:"h"` | |
I string `csv:"i" name:"i"` | |
J int `csv:"j" name:"j"` | |
K time.Time `csv:"k" name:"k"` | |
L time.Time `csv:"l" name:"l"` | |
} | |
func UnmarshalDate(s string, v interface{}) (err error) { | |
*(v.(*time.Time)), err = time.Parse("2006.01.02", s) | |
if err != nil { | |
return err | |
} | |
return nil | |
} | |
func ConvertDate(s string) string { | |
date, err := time.Parse("2006.01.02", s) | |
if err != nil { | |
return "" | |
} | |
return date.Format(time.RFC3339) | |
} | |
func BenchmarkUnmarshal(b *testing.B) { | |
fixture := []struct { | |
desc string | |
records int | |
}{ | |
{ | |
desc: "1 record", | |
records: 1, | |
}, | |
{ | |
desc: "10 records", | |
records: 10, | |
}, | |
{ | |
desc: "100 records", | |
records: 100, | |
}, | |
{ | |
desc: "1000 records", | |
records: 1000, | |
}, | |
{ | |
desc: "10000 records", | |
records: 10000, | |
}, | |
{ | |
desc: "100000 records", | |
records: 100000, | |
}, | |
} | |
tests := []struct { | |
desc string | |
fn func([]byte, *testing.B) | |
}{ | |
{ | |
desc: "csvutildk.Unmarshal", | |
fn: func(data []byte, b *testing.B) { | |
var a []A | |
dec, err := csvutildk.NewDecoder(csv.NewReader(bytes.NewReader(data))) | |
if err != nil { | |
b.Error(err) | |
} | |
dec.FnMap = func(name string, v interface{}) csvutildk.DecodeFunc { | |
if name == "k" { | |
return UnmarshalDate | |
} | |
if _, ok := v.(time.Time); ok { | |
return UnmarshalDate | |
} | |
return nil | |
} | |
for { | |
value := A{} | |
if err := dec.Decode(&value); err == io.EOF { | |
break | |
} else if err != nil { | |
b.Error(err) | |
} | |
a = append(a, value) | |
} | |
}, | |
}, | |
{ | |
desc: "csvutil.Unmarshal", | |
fn: func(data []byte, b *testing.B) { | |
var a []A | |
dec, err := csvutil.NewDecoder(csv.NewReader(bytes.NewReader(data))) | |
if err != nil { | |
b.Error(err) | |
} | |
dec.Map = func(field, column string, v interface{}) string { | |
if column == "k" { | |
return ConvertDate(field) | |
} | |
if _, ok := v.(time.Time); ok { | |
return ConvertDate(field) | |
} | |
return field | |
} | |
for { | |
value := A{} | |
if err := dec.Decode(&value); err == io.EOF { | |
break | |
} else if err != nil { | |
b.Error(err) | |
} | |
a = append(a, value) | |
} | |
}, | |
}, | |
} | |
for _, t := range tests { | |
b.Run(t.desc, func(b *testing.B) { | |
for _, f := range fixture { | |
b.Run(f.desc, func(b *testing.B) { | |
data := genData(f.records) | |
for i := 0; i < b.N; i++ { | |
t.fn(data, b) | |
} | |
}) | |
} | |
}) | |
} | |
} | |
func genData(records int) []byte { | |
header := []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"} | |
record := []string{"1", "2.5", "foo", "6", "7", "8", "9", "10", "bar", "10", "2019.08.31", "2019.08.31"} | |
var buf bytes.Buffer | |
w := csv.NewWriter(&buf) | |
w.Write(header) | |
for i := 0; i < records; i++ { | |
w.Write(record) | |
} | |
w.Flush() | |
if err := w.Error(); err != nil { | |
panic(err) | |
} | |
return buf.Bytes() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment