diff --git a/app/vmselect/promql/aggr.go b/app/vmselect/promql/aggr.go index 6bd094ae3..84c459915 100644 --- a/app/vmselect/promql/aggr.go +++ b/app/vmselect/promql/aggr.go @@ -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. func quantiles(qs, phis []float64, originValues []float64) []float64 { a := getFloat64s() - a.A = prepareForQuantileFloat64(a.A[:0], originValues) + a.prepareForQuantileFloat64(originValues) qs = quantilesSorted(qs, phis, a.A) putFloat64s(a) return qs @@ -828,22 +828,38 @@ func quantiles(qs, phis []float64, originValues []float64) []float64 { // quantile calculates the given phi from originValues without modifying originValues func quantile(phi float64, originValues []float64) float64 { a := getFloat64s() - a.A = prepareForQuantileFloat64(a.A[:0], originValues) + a.prepareForQuantileFloat64(originValues) q := quantileSorted(phi, a.A) putFloat64s(a) return q } -// prepareForQuantileFloat64 copies items from src to dst but removes NaNs and sorts the dst -func prepareForQuantileFloat64(dst, src []float64) []float64 { +// prepareForQuantileFloat64 copies items from src to a but removes NaNs and sorts items in a. +func (a *float64s) prepareForQuantileFloat64(src []float64) { + dst := a.A[:0] for _, v := range src { if math.IsNaN(v) { continue } dst = append(dst, v) } - sort.Float64s(dst) - return dst + a.A = 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.