Skip to content

Commit 57a8206

Browse files
timwintleecharrod
andauthored
optimisation: Maintain a lookup of frequently used big.Int instances (#154)
* Maintain a small lookup of the first few big.Ints - reduces GC pressure significantly * Update decimal/decimal.go --------- Co-authored-by: Ed Harrod <echarrod@users.noreply.github.com>
1 parent 6123d97 commit 57a8206

File tree

1 file changed

+22
-6
lines changed

1 file changed

+22
-6
lines changed

decimal/decimal.go

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,22 @@ import (
88
"strings"
99
)
1010

11+
// Maintain references to common big.Ints to reduce GC pressure
12+
var bigIntLookup = [32]*big.Int{}
13+
14+
func init() {
15+
for i := 0; i < len(bigIntLookup); i++ {
16+
bigIntLookup[i] = big.NewInt(int64(i))
17+
}
18+
}
19+
20+
func cachedBigInt(i int64) *big.Int {
21+
if i >= 0 && i < int64(len(bigIntLookup)) {
22+
return bigIntLookup[i]
23+
}
24+
return big.NewInt(i)
25+
}
26+
1127
// Decimal represents a decimal amount, internally stored as a big.Int.
1228
type Decimal struct {
1329
i *big.Int
@@ -26,7 +42,7 @@ func New(i *big.Int, scale int) Decimal {
2642
}
2743

2844
func NewFromInt64(i int64) Decimal {
29-
return New(big.NewInt(i), 0)
45+
return New(cachedBigInt(i), 0)
3046
}
3147

3248
// NewFromFloat64 returns a new Decimal with the given scale. The value is
@@ -54,7 +70,7 @@ func NewFromString(s string) (Decimal, error) {
5470

5571
// Zero returns a Decimal representing 0, with precision 0.
5672
func Zero() Decimal {
57-
return New(big.NewInt(0), 0)
73+
return New(cachedBigInt(0), 0)
5874
}
5975

6076
// MarshalJSON converts the Decimal to JSON bytes.
@@ -109,7 +125,7 @@ func (d Decimal) Float64() float64 {
109125
}
110126

111127
scale := big.NewInt(int64(d.scale))
112-
scale.Exp(big.NewInt(10), scale, nil)
128+
scale.Exp(cachedBigInt(10), scale, nil)
113129

114130
r := new(big.Rat)
115131
r.SetFrac(bigIntDefault(d.i), scale)
@@ -128,7 +144,7 @@ func (d Decimal) ToScale(scale int) Decimal {
128144
exponent = -exponent
129145
}
130146
s := new(big.Int)
131-
s.Exp(big.NewInt(10), big.NewInt(int64(exponent)), nil)
147+
s.Exp(cachedBigInt(10), cachedBigInt(int64(exponent)), nil)
132148
di := bigIntDefault(d.i)
133149
o := new(big.Int)
134150
if d.scale > scale {
@@ -179,13 +195,13 @@ func (d Decimal) Sub(y Decimal) Decimal {
179195
// MulInt64 multiplies d by y and returns the result. d is left unchanged.
180196
func (d Decimal) MulInt64(y int64) Decimal {
181197
di := bigIntDefault(d.i)
182-
return New(new(big.Int).Mul(di, big.NewInt(y)), d.scale)
198+
return New(new(big.Int).Mul(di, cachedBigInt(y)), d.scale)
183199
}
184200

185201
// DivInt64 divides d by y and returns the result. d is left unchanged.
186202
func (d Decimal) DivInt64(y int64) Decimal {
187203
di := bigIntDefault(d.i)
188-
return New(new(big.Int).Div(di, big.NewInt(y)), d.scale)
204+
return New(new(big.Int).Div(di, cachedBigInt(y)), d.scale)
189205
}
190206

191207
// Mul multiplies d by y and returns the result. The result has a scale equal to

0 commit comments

Comments
 (0)