From 092c9b39a8f2bdc10497ad134906ff5ccec0eabc Mon Sep 17 00:00:00 2001 From: Aliaksandr Valialkin Date: Fri, 12 Jul 2019 19:56:23 +0300 Subject: [PATCH] app/vmselect/promql: remove empty time series after applying filters like `q > 0` This should reduce CPU and RAM usage for queries over high number of time series. --- app/vmselect/promql/binary_op.go | 3 +++ app/vmselect/promql/exec.go | 13 +++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/app/vmselect/promql/binary_op.go b/app/vmselect/promql/binary_op.go index f8ff4c60a..7bde1cab5 100644 --- a/app/vmselect/promql/binary_op.go +++ b/app/vmselect/promql/binary_op.go @@ -260,6 +260,9 @@ func newBinaryOpFunc(bf func(left, right float64, isBool bool) float64) binaryOp dstValues[j] = bf(a, b, isBool) } } + // Optimization: remove time series containing only NaNs. + // This is quite common after applying filters like `q > 0`. + dst = removeNaNs(dst) return dst, nil } } diff --git a/app/vmselect/promql/exec.go b/app/vmselect/promql/exec.go index 42ffbd6ae..c7b0e2f39 100644 --- a/app/vmselect/promql/exec.go +++ b/app/vmselect/promql/exec.go @@ -131,18 +131,23 @@ func timeseriesToResult(tss []*timeseries, maySort bool) ([]netstorage.Result, e func removeNaNs(tss []*timeseries) []*timeseries { rvs := tss[:0] for _, ts := range tss { - nans := 0 + allNans := true for _, v := range ts.Values { - if math.IsNaN(v) { - nans++ + if !math.IsNaN(v) { + allNans = false + break } } - if nans == len(ts.Values) { + if allNans { // Skip timeseries with all NaNs. continue } rvs = append(rvs, ts) } + for i := len(rvs); i < len(tss); i++ { + // Zero unused time series, so GC could reclaim them. + tss[i] = nil + } return rvs }