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:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user