app/vmselect/promql: eliminate memory allocation when sorting values inside float64s

This commit is contained in:
Aliaksandr Valialkin 2023-01-09 23:06:46 -08:00
parent 30ed33fae0
commit 9a563a6aef
No known key found for this signature in database
GPG key ID: A72BEC6CD3D0DED1

View file

@ -819,7 +819,7 @@ func lastValue(values []float64) float64 {
// quantiles calculates the given phis from originValues without modifying originValues, appends them to qs and returns the result. // quantiles calculates the given phis from originValues without modifying originValues, appends them to qs and returns the result.
func quantiles(qs, phis []float64, originValues []float64) []float64 { func quantiles(qs, phis []float64, originValues []float64) []float64 {
a := getFloat64s() a := getFloat64s()
a.A = prepareForQuantileFloat64(a.A[:0], originValues) a.prepareForQuantileFloat64(originValues)
qs = quantilesSorted(qs, phis, a.A) qs = quantilesSorted(qs, phis, a.A)
putFloat64s(a) putFloat64s(a)
return qs return qs
@ -828,22 +828,38 @@ func quantiles(qs, phis []float64, originValues []float64) []float64 {
// quantile calculates the given phi from originValues without modifying originValues // quantile calculates the given phi from originValues without modifying originValues
func quantile(phi float64, originValues []float64) float64 { func quantile(phi float64, originValues []float64) float64 {
a := getFloat64s() a := getFloat64s()
a.A = prepareForQuantileFloat64(a.A[:0], originValues) a.prepareForQuantileFloat64(originValues)
q := quantileSorted(phi, a.A) q := quantileSorted(phi, a.A)
putFloat64s(a) putFloat64s(a)
return q return q
} }
// prepareForQuantileFloat64 copies items from src to dst but removes NaNs and sorts the dst // prepareForQuantileFloat64 copies items from src to a but removes NaNs and sorts items in a.
func prepareForQuantileFloat64(dst, src []float64) []float64 { func (a *float64s) prepareForQuantileFloat64(src []float64) {
dst := a.A[:0]
for _, v := range src { for _, v := range src {
if math.IsNaN(v) { if math.IsNaN(v) {
continue continue
} }
dst = append(dst, v) dst = append(dst, v)
} }
sort.Float64s(dst) a.A = dst
return dst // Use sort.Sort instead of sort.Float64s in order to avoid a memory allocation
sort.Sort(a)
}
func (a *float64s) Len() int {
return len(a.A)
}
func (a *float64s) Swap(i, j int) {
x := a.A
x[i], x[j] = x[j], x[i]
}
func (a *float64s) Less(i, j int) bool {
x := a.A
return x[i] < x[j]
} }
// quantilesSorted calculates the given phis over a sorted list of values, appends them to qs and returns the result. // quantilesSorted calculates the given phis over a sorted list of values, appends them to qs and returns the result.