lib/decimal: follow-up for e6bad5174f

- Add a benchmark for CalbirateAndScale.
- Reduce the decimal multipliers table size from 256Kb to 192bytes.
- Use more clear naming for variables.

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/pull/5672
This commit is contained in:
Aliaksandr Valialkin 2024-01-26 23:53:16 +01:00
parent 64780f4f02
commit 0ed291102d
No known key found for this signature in database
GPG Key ID: 52C003EE2BCDB9EB
2 changed files with 50 additions and 22 deletions

View File

@ -7,20 +7,6 @@ import (
"github.com/VictoriaMetrics/VictoriaMetrics/lib/fastnum" "github.com/VictoriaMetrics/VictoriaMetrics/lib/fastnum"
) )
const tableLen = 32767
var table = func() []int64 {
out := make([]int64, 0, tableLen)
var cur int64 = 10
for i := 1; i <= tableLen; i++ {
out = append(out, cur)
if cur*10 > 0 {
cur *= 10
}
}
return out
}()
// CalibrateScale calibrates a and b with the corresponding exponents ae, be // CalibrateScale calibrates a and b with the corresponding exponents ae, be
// and returns the resulting exponent e. // and returns the resulting exponent e.
func CalibrateScale(a []int64, ae int16, b []int64, be int16) (e int16) { func CalibrateScale(a []int64, ae int16, b []int64, be int16) (e int16) {
@ -49,29 +35,49 @@ func CalibrateScale(a []int64, ae int16, b []int64, be int16) (e int16) {
} }
} }
upExp -= downExp upExp -= downExp
if upExp > 0 { if upExp > 0 {
times := table[upExp-1] m := getDecimalMultiplier(uint16(upExp))
for i, v := range a { for i, v := range a {
if isSpecialValue(v) { if isSpecialValue(v) {
// Do not take into account special values. // Do not take into account special values.
continue continue
} }
a[i] = v * times a[i] = v * m
} }
} }
if downExp > 0 { if downExp > 0 {
times := table[downExp-1] if downExp > 18 {
for i, v := range b { for i, v := range b {
if isSpecialValue(v) { if isSpecialValue(v) {
// Do not take into account special values. // Do not take into account special values.
continue continue
}
b[i] = 0
}
} else {
m := getDecimalMultiplier(uint16(downExp))
for i, v := range b {
if isSpecialValue(v) {
// Do not take into account special values.
continue
}
b[i] = v / m
} }
b[i] = v / times
} }
} }
return be + downExp return be + downExp
} }
func getDecimalMultiplier(exp uint16) int64 {
if exp >= uint16(len(decimalMultipliers)) {
return 1
}
return decimalMultipliers[exp]
}
var decimalMultipliers = []int64{1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18}
// ExtendFloat64sCapacity extends dst capacity to hold additionalItems // ExtendFloat64sCapacity extends dst capacity to hold additionalItems
// and returns the extended dst. // and returns the extended dst.
func ExtendFloat64sCapacity(dst []float64, additionalItems int) []float64 { func ExtendFloat64sCapacity(dst []float64, additionalItems int) []float64 {

View File

@ -7,6 +7,28 @@ import (
"testing" "testing"
) )
func BenchmarkCalbirateScale(b *testing.B) {
aSrc := []int64{1, 2, 3, 4, 5, 67, 8, 9, 12, 324, 29, -34, -94, -84, -34, 0, 2, 3}
bSrc := []int64{2, 3, 4, 5, 67, 8, 9, 12, 324, 29, -34, -94, -84, -34, 0, 2, 3, 1}
const aScale = 1
const bScale = 2
const scaleExpected = 1
b.ReportAllocs()
b.SetBytes(int64(len(aSrc)))
b.RunParallel(func(pb *testing.PB) {
var a, b []int64
for pb.Next() {
a = append(a[:0], aSrc...)
b = append(b[:0], bSrc...)
scale := CalibrateScale(a, aScale, b, bScale)
if scale != scaleExpected {
panic(fmt.Errorf("unexpected scale; got %d; want %d", scale, scaleExpected))
}
}
})
}
func BenchmarkAppendDecimalToFloat(b *testing.B) { func BenchmarkAppendDecimalToFloat(b *testing.B) {
b.Run("RealFloat", func(b *testing.B) { b.Run("RealFloat", func(b *testing.B) {
benchmarkAppendDecimalToFloat(b, testVA, vaScale) benchmarkAppendDecimalToFloat(b, testVA, vaScale)