Skip to content

Commit 12309ac

Browse files
committed
msgpack: add string() for decimal, datetime. interval
Added a benchmark, which shows that the code for decimal is optimized two or more times for string conversion than the code from the library. Added a datetime Interval type conversion function to a string, added tests for this function. Added #322
1 parent e75bd84 commit 12309ac

File tree

3 files changed

+28
-28
lines changed

3 files changed

+28
-28
lines changed

decimal/decimal.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ func (d Decimal) MarshalMsgpack() ([]byte, error) {
9999
// +--------+-------------------+------------+===============+
100100
// | MP_EXT | length (optional) | MP_DECIMAL | PackedDecimal |
101101
// +--------+-------------------+------------+===============+
102-
strBuf := d.String()
102+
strBuf := d.Decimal.String()
103103
bcdBuf, err := encodeStringToBCD(strBuf)
104104
if err != nil {
105105
return nil, fmt.Errorf("msgpack: can't encode string (%s) to a BCD buffer: %w", strBuf, err)
@@ -149,14 +149,14 @@ func decimalDecoder(d *msgpack.Decoder, v reflect.Value, extLen int) error {
149149

150150
// This method converts the decimal type to a string.
151151
// Use shopspring/decimal by default.
152-
// StringOptimized - optimized version for Tarantool Decimal
152+
// String - optimized version for Tarantool Decimal
153153
// taking into account the limitations of int64 and support for large numbers via fallback
154154
// Tarantool decimal has 38 digits, which can exceed int64.
155155
// Therefore, we cannot use int64 for all cases.
156156
// For the general case, use shopspring/decimal.String().
157157
// For cases where it is known that numbers contain less than 26 characters,
158158
// you can use the optimized version.
159-
func (d Decimal) StringOptimized() string {
159+
func (d Decimal) String() string {
160160
coefficient := d.Decimal.Coefficient() // Note: In shopspring/decimal, the number is stored as coefficient *10^exponent, where exponent can be negative.
161161
exponent := d.Decimal.Exponent()
162162

decimal/decimal_bench_test.go

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ import (
1212
func BenchmarkMinimal(b *testing.B) {
1313
dec := MustMakeDecimal("123.45")
1414

15-
b.Run("StringOptimized", func(b *testing.B) {
15+
b.Run("String", func(b *testing.B) {
1616
for i := 0; i < b.N; i++ {
17-
_ = dec.StringOptimized()
17+
_ = dec.String()
1818
}
1919
})
2020

@@ -46,10 +46,10 @@ func BenchmarkDecimalString_SmallNumbers(b *testing.B) {
4646
}
4747

4848
b.ResetTimer()
49-
b.Run("StringOptimized", func(b *testing.B) {
49+
b.Run("String", func(b *testing.B) {
5050
for i := 0; i < b.N; i++ {
5151
for _, dec := range decimals {
52-
_ = dec.StringOptimized()
52+
_ = dec.String()
5353
}
5454
}
5555
})
@@ -78,10 +78,10 @@ func BenchmarkDecimalString_Int64Boundaries(b *testing.B) {
7878
}
7979

8080
b.ResetTimer()
81-
b.Run("StringOptimized", func(b *testing.B) {
81+
b.Run("String", func(b *testing.B) {
8282
for i := 0; i < b.N; i++ {
8383
for _, dec := range decimals {
84-
_ = dec.StringOptimized()
84+
_ = dec.String()
8585
}
8686
}
8787
})
@@ -110,10 +110,10 @@ func BenchmarkDecimalString_LargeNumbers(b *testing.B) {
110110
}
111111

112112
b.ResetTimer()
113-
b.Run("StringOptimized", func(b *testing.B) {
113+
b.Run("String", func(b *testing.B) {
114114
for i := 0; i < b.N; i++ {
115115
for _, dec := range decimals {
116-
_ = dec.StringOptimized()
116+
_ = dec.String()
117117
}
118118
}
119119
})
@@ -147,10 +147,10 @@ func BenchmarkDecimalString_Mixed(b *testing.B) {
147147
}
148148

149149
b.ResetTimer()
150-
b.Run("StringOptimized", func(b *testing.B) {
150+
b.Run("String", func(b *testing.B) {
151151
for i := 0; i < b.N; i++ {
152152
for _, dec := range decimals {
153-
_ = dec.StringOptimized()
153+
_ = dec.String()
154154
}
155155
}
156156
})
@@ -180,9 +180,9 @@ func BenchmarkDecimalString_DifferentPrecision(b *testing.B) {
180180
b.Run(tc.name, func(b *testing.B) {
181181
dec := MustMakeDecimal(tc.value)
182182

183-
b.Run("StringOptimized", func(b *testing.B) {
183+
b.Run("String", func(b *testing.B) {
184184
for i := 0; i < b.N; i++ {
185-
_ = dec.StringOptimized()
185+
_ = dec.String()
186186
}
187187
})
188188

@@ -275,11 +275,11 @@ func BenchmarkDecimalString_Random(b *testing.B) {
275275
}
276276

277277
b.ResetTimer()
278-
b.Run("StringOptimized", func(b *testing.B) {
278+
b.Run("String", func(b *testing.B) {
279279
total := 0
280280
for i := 0; i < b.N; i++ {
281281
dec := generateRandomDecimal()
282-
result := dec.StringOptimized()
282+
result := dec.String()
283283
total += len(result)
284284
}
285285
_ = total
@@ -312,10 +312,10 @@ func BenchmarkDecimalString_MemoryAllocations(b *testing.B) {
312312

313313
b.ResetTimer()
314314

315-
b.Run("StringOptimized", func(b *testing.B) {
315+
b.Run("String", func(b *testing.B) {
316316
for i := 0; i < b.N; i++ {
317317
for _, dec := range decimals {
318-
_ = dec.StringOptimized()
318+
_ = dec.String()
319319
}
320320
}
321321
})

decimal/decimal_test.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,7 @@ func TestMain(m *testing.M) {
703703
os.Exit(code)
704704
}
705705

706-
func TestDecimalStringOptimized(t *testing.T) {
706+
func TestDecimalString(t *testing.T) {
707707
tests := []struct {
708708
name string
709709
input string
@@ -770,7 +770,7 @@ func TestDecimalStringOptimized(t *testing.T) {
770770
dec, err := MakeDecimalFromString(tt.input)
771771
assert.NoError(t, err)
772772

773-
result := dec.StringOptimized()
773+
result := dec.String()
774774

775775
assert.Equal(t, tt.expected, result)
776776

@@ -802,8 +802,8 @@ func TestTarantoolBCDCompatibility(t *testing.T) {
802802
err = dec2.UnmarshalMsgpack(msgpackData)
803803
assert.NoError(t, err)
804804

805-
originalStr := dec.StringOptimized()
806-
roundtripStr := dec2.StringOptimized()
805+
originalStr := dec.String()
806+
roundtripStr := dec2.String()
807807

808808
assert.Equal(t, originalStr, roundtripStr,
809809
"BCD roundtrip failed for input: %s", input)
@@ -863,11 +863,11 @@ func Test100_00(t *testing.T) {
863863
if coefficient.IsInt64() {
864864
t.Logf("Int64: %v", coefficient.Int64())
865865
}
866-
result := dec.StringOptimized()
867-
t.Logf("StringOptimized: %q", result)
866+
result := dec.String()
867+
t.Logf("String: %q", result)
868868
}
869869

870-
func TestLargeNumberStringOptimized(t *testing.T) {
870+
func TestLargeNumberString(t *testing.T) {
871871
largeNumber := "123456789012345678901234567890.123456789"
872872
dec, err := MakeDecimalFromString(largeNumber)
873873
if err != nil {
@@ -880,7 +880,7 @@ func TestLargeNumberStringOptimized(t *testing.T) {
880880
t.Error("Expected coefficient to be too large for int64")
881881
}
882882

883-
optimized := dec.StringOptimized()
883+
optimized := dec.String()
884884
standard := dec.Decimal.String()
885885

886886
if optimized != standard {
@@ -910,7 +910,7 @@ func TestDecimalTrailingZeros(t *testing.T) {
910910
for _, tt := range tests {
911911
t.Run(tt.input, func(t *testing.T) {
912912
dec := MustMakeDecimal(tt.input)
913-
result := dec.StringOptimized()
913+
result := dec.String()
914914
if result != tt.expected {
915915
t.Errorf("For %s: expected %s, got %s", tt.input, tt.expected, result)
916916
}

0 commit comments

Comments
 (0)