From 3e6c4a6c79023dc6d87f66c4cdfa6937bb99f6ac Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 4 May 2021 06:32:15 +0700 Subject: [PATCH] types: make chopPrecisionAndTruncate always non-mutative (#9250) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, chopPrecisionAndTruncate/chopPrecisionAndTruncateNonMutative are doing the same thing, except that the former do it mutatively. Looking at the usages of chopPrecisionAndTruncate, the callers must alloc a new big.Int before calling it anyway, so any mutation will be done with this new allocated big.Int, instead of input argument. So, by making chopPrecisionAndTruncate always non-mutative, we simplify the code, and make the code faster, less allocation in some benchmarks. Benchmark for github.com/cosmos/cosmos-sdk/types: name old time/op new time/op delta CoinsAdditionIntersect/sizes:_A_1,_B_1-8 35.4ns ± 0% 35.1ns ± 0% -0.92% (p=0.008 n=5+5) CoinsAdditionIntersect/sizes:_A_5,_B_5-8 366ns ± 1% 363ns ± 1% ~ (p=0.056 n=5+5) CoinsAdditionIntersect/sizes:_A_5,_B_20-8 557ns ± 0% 553ns ± 0% -0.64% (p=0.008 n=5+5) CoinsAdditionIntersect/sizes:_A_1,_B_1000-8 6.17µs ± 0% 6.18µs ± 0% ~ (p=0.151 n=5+5) CoinsAdditionIntersect/sizes:_A_2,_B_1000-8 6.30µs ± 0% 6.32µs ± 0% +0.23% (p=0.008 n=5+5) CoinsAdditionNoIntersect/sizes:_A_1,_B_1-8 30.2ns ± 0% 29.9ns ± 1% -0.98% (p=0.008 n=5+5) CoinsAdditionNoIntersect/sizes:_A_5,_B_5-8 226ns ± 0% 224ns ± 0% -0.54% (p=0.008 n=5+5) CoinsAdditionNoIntersect/sizes:_A_5,_B_20-8 373ns ± 0% 372ns ± 0% -0.26% (p=0.040 n=5+5) CoinsAdditionNoIntersect/sizes:_A_1,_B_1000-8 6.21µs ± 0% 6.22µs ± 0% ~ (p=0.421 n=5+5) CoinsAdditionNoIntersect/sizes:_A_2,_B_1000-8 6.22µs ± 0% 6.23µs ± 0% ~ (p=0.286 n=5+5) CoinsAdditionNoIntersect/sizes:_A_1000,_B_2-8 6.22µs ± 0% 6.23µs ± 0% ~ (p=0.143 n=5+5) ParseCoin-8 5.46µs ± 0% 5.39µs ± 0% -1.26% (p=0.008 n=5+5) UintMarshal-8 1.01µs ± 0% 1.00µs ± 0% -1.10% (p=0.008 n=5+5) IntMarshal-8 764ns ± 0% 758ns ± 1% -0.79% (p=0.024 n=5+5) MarshalTo-8 192ns ± 0% 190ns ± 0% -1.03% (p=0.008 n=5+5) name old alloc/op new alloc/op delta CoinsAdditionIntersect/sizes:_A_1,_B_1-8 32.0B ± 0% 32.0B ± 0% ~ (all equal) CoinsAdditionIntersect/sizes:_A_5,_B_5-8 520B ± 0% 520B ± 0% ~ (all equal) CoinsAdditionIntersect/sizes:_A_5,_B_20-8 1.38kB ± 0% 1.38kB ± 0% ~ (all equal) CoinsAdditionIntersect/sizes:_A_1,_B_1000-8 49.2kB ± 0% 49.2kB ± 0% ~ (all equal) CoinsAdditionIntersect/sizes:_A_2,_B_1000-8 49.3kB ± 0% 49.3kB ± 0% ~ (all equal) CoinsAdditionNoIntersect/sizes:_A_1,_B_1-8 24.0B ± 0% 24.0B ± 0% ~ (all equal) CoinsAdditionNoIntersect/sizes:_A_5,_B_5-8 488B ± 0% 488B ± 0% ~ (all equal) CoinsAdditionNoIntersect/sizes:_A_5,_B_20-8 1.35kB ± 0% 1.35kB ± 0% ~ (all equal) CoinsAdditionNoIntersect/sizes:_A_1,_B_1000-8 49.2kB ± 0% 49.2kB ± 0% ~ (all equal) CoinsAdditionNoIntersect/sizes:_A_2,_B_1000-8 49.2kB ± 0% 49.2kB ± 0% ~ (all equal) CoinsAdditionNoIntersect/sizes:_A_1000,_B_2-8 49.2kB ± 0% 49.2kB ± 0% ~ (all equal) ParseCoin-8 2.21kB ± 0% 2.21kB ± 0% ~ (all equal) UintMarshal-8 392B ± 0% 392B ± 0% ~ (all equal) IntMarshal-8 168B ± 0% 168B ± 0% ~ (all equal) MarshalTo-8 80.0B ± 0% 80.0B ± 0% ~ (all equal) name old allocs/op new allocs/op delta CoinsAdditionIntersect/sizes:_A_1,_B_1-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) CoinsAdditionIntersect/sizes:_A_5,_B_5-8 12.0 ± 0% 12.0 ± 0% ~ (all equal) CoinsAdditionIntersect/sizes:_A_5,_B_20-8 14.0 ± 0% 14.0 ± 0% ~ (all equal) CoinsAdditionIntersect/sizes:_A_1,_B_1000-8 3.00 ± 0% 3.00 ± 0% ~ (all equal) CoinsAdditionIntersect/sizes:_A_2,_B_1000-8 6.00 ± 0% 6.00 ± 0% ~ (all equal) CoinsAdditionNoIntersect/sizes:_A_1,_B_1-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) CoinsAdditionNoIntersect/sizes:_A_5,_B_5-8 5.00 ± 0% 5.00 ± 0% ~ (all equal) CoinsAdditionNoIntersect/sizes:_A_5,_B_20-8 6.00 ± 0% 6.00 ± 0% ~ (all equal) CoinsAdditionNoIntersect/sizes:_A_1,_B_1000-8 3.00 ± 0% 3.00 ± 0% ~ (all equal) CoinsAdditionNoIntersect/sizes:_A_2,_B_1000-8 4.00 ± 0% 4.00 ± 0% ~ (all equal) CoinsAdditionNoIntersect/sizes:_A_1000,_B_2-8 3.00 ± 0% 3.00 ± 0% ~ (all equal) ParseCoin-8 71.0 ± 0% 71.0 ± 0% ~ (all equal) UintMarshal-8 25.0 ± 0% 25.0 ± 0% ~ (all equal) IntMarshal-8 18.0 ± 0% 18.0 ± 0% ~ (all equal) MarshalTo-8 2.00 ± 0% 2.00 ± 0% ~ (all equal) name old speed new speed delta UintMarshal-8 6.91MB/s ± 0% 6.99MB/s ± 0% +1.04% (p=0.008 n=5+5) IntMarshal-8 9.16MB/s ± 0% 9.23MB/s ± 1% +0.83% (p=0.032 n=5+5) Benchmark for github.com/cosmos/cosmos-sdk/x/mint/types: name old time/op new time/op delta BlockProvision-8 263ns ± 0% 257ns ± 0% -2.23% (p=0.008 n=5+5) name old alloc/op new alloc/op delta BlockProvision-8 112B ± 0% 104B ± 0% -7.14% (p=0.008 n=5+5) name old allocs/op new allocs/op delta BlockProvision-8 6.00 ± 0% 5.00 ± 0% -16.67% (p=0.008 n=5+5) Fixes #9249 Co-authored-by: Emmanuel T Odeke --- types/decimal.go | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/types/decimal.go b/types/decimal.go index 9ce5cfb97237..365b8c8c918c 100644 --- a/types/decimal.go +++ b/types/decimal.go @@ -301,7 +301,7 @@ func (d Dec) QuoTruncate(d2 Dec) Dec { mul := new(big.Int).Mul(d.i, precisionReuse) mul.Mul(mul, precisionReuse) - quo := new(big.Int).Quo(mul, d2.i) + quo := mul.Quo(mul, d2.i) chopped := chopPrecisionAndTruncate(quo) if chopped.BitLen() > 255+DecimalPrecisionBits { @@ -560,19 +560,15 @@ func (d Dec) RoundInt() Int { return NewIntFromBigInt(chopPrecisionAndRoundNonMutative(d.i)) } -// similar to chopPrecisionAndRound, but always rounds down +// chopPrecisionAndTruncate is similar to chopPrecisionAndRound, +// but always rounds down. It does not mutate the input. func chopPrecisionAndTruncate(d *big.Int) *big.Int { - return d.Quo(d, precisionReuse) -} - -func chopPrecisionAndTruncateNonMutative(d *big.Int) *big.Int { - tmp := new(big.Int).Set(d) - return chopPrecisionAndTruncate(tmp) + return new(big.Int).Quo(d, precisionReuse) } // TruncateInt64 truncates the decimals from the number and returns an int64 func (d Dec) TruncateInt64() int64 { - chopped := chopPrecisionAndTruncateNonMutative(d.i) + chopped := chopPrecisionAndTruncate(d.i) if !chopped.IsInt64() { panic("Int64() out of bound") } @@ -581,12 +577,12 @@ func (d Dec) TruncateInt64() int64 { // TruncateInt truncates the decimals from the number and returns an Int func (d Dec) TruncateInt() Int { - return NewIntFromBigInt(chopPrecisionAndTruncateNonMutative(d.i)) + return NewIntFromBigInt(chopPrecisionAndTruncate(d.i)) } // TruncateDec truncates the decimals from the number and returns a Dec func (d Dec) TruncateDec() Dec { - return NewDecFromBigInt(chopPrecisionAndTruncateNonMutative(d.i)) + return NewDecFromBigInt(chopPrecisionAndTruncate(d.i)) } // Ceil returns the smallest interger value (as a decimal) that is greater than