2
0

Improved ext/shopspring-numeric binary decoding performance

Before:
BenchmarkDecode/Zero-Binary-16       	 3944304	       292 ns/op	     128 B/op	       7 allocs/op
BenchmarkDecode/Small-Binary-16      	 2034132	       585 ns/op	     184 B/op	      13 allocs/op
BenchmarkDecode/Medium-Binary-16     	 1747191	       690 ns/op	     192 B/op	      12 allocs/op
BenchmarkDecode/Large-Binary-16      	 1334006	       899 ns/op	     304 B/op	      14 allocs/op
BenchmarkDecode/Huge-Binary-16       	  702382	      1590 ns/op	     584 B/op	      18 allocs/op

After:
BenchmarkDecode/Zero-Binary-16       	14592645	        80.1 ns/op	      64 B/op	       2 allocs/op
BenchmarkDecode/Small-Binary-16      	 5729318	       212 ns/op	     104 B/op	       7 allocs/op
BenchmarkDecode/Medium-Binary-16     	 4930009	       241 ns/op	      88 B/op	       5 allocs/op
BenchmarkDecode/Large-Binary-16      	 3369573	       344 ns/op	     144 B/op	       7 allocs/op
BenchmarkDecode/Huge-Binary-16       	 2587156	       453 ns/op	     216 B/op	       9 allocs/op
This commit is contained in:
Jack Christensen
2020-05-02 11:34:14 -05:00
parent 98c9ec4f7b
commit e6c6de9494
2 changed files with 45 additions and 11 deletions
+1 -11
View File
@@ -250,17 +250,7 @@ func (dst *Numeric) DecodeBinary(ci *pgtype.ConnInfo, src []byte) error {
return err
}
buf, err := num.EncodeText(ci, nil)
if err != nil {
return err
}
dec, err := decimal.NewFromString(string(buf))
if err != nil {
return err
}
*dst = Numeric{Decimal: dec, Status: pgtype.Present}
*dst = Numeric{Decimal: decimal.NewFromBigInt(num.Int, num.Exp), Status: pgtype.Present}
return nil
}
+44
View File
@@ -11,6 +11,7 @@ import (
shopspring "github.com/jackc/pgtype/ext/shopspring-numeric"
"github.com/jackc/pgtype/testutil"
"github.com/shopspring/decimal"
"github.com/stretchr/testify/require"
)
func mustParseDecimal(t *testing.T, src string) decimal.Decimal {
@@ -284,3 +285,46 @@ func TestNumericAssignTo(t *testing.T) {
}
}
}
func BenchmarkDecode(b *testing.B) {
benchmarks := []struct {
name string
numberStr string
}{
{"Zero", "0"},
{"Small", "12345"},
{"Medium", "12345.12345"},
{"Large", "123457890.1234567890"},
{"Huge", "123457890123457890123457890.1234567890123457890123457890"},
}
for _, bm := range benchmarks {
src := &shopspring.Numeric{}
err := src.Set(bm.numberStr)
require.NoError(b, err)
textFormat, err := src.EncodeText(nil, nil)
require.NoError(b, err)
binaryFormat, err := src.EncodeBinary(nil, nil)
require.NoError(b, err)
b.Run(fmt.Sprintf("%s-Text", bm.name), func(b *testing.B) {
dst := &shopspring.Numeric{}
for i := 0; i < b.N; i++ {
err := dst.DecodeText(nil, textFormat)
if err != nil {
b.Fatal(err)
}
}
})
b.Run(fmt.Sprintf("%s-Binary", bm.name), func(b *testing.B) {
dst := &shopspring.Numeric{}
for i := 0; i < b.N; i++ {
err := dst.DecodeBinary(nil, binaryFormat)
if err != nil {
b.Fatal(err)
}
}
})
}
}