@ -1452,6 +1452,7 @@ func (ev *evaluator) eval(expr parser.Expr) (parser.Value, annotations.Annotatio
// Reuse objects across steps to save memory allocations.
var floats [ ] FPoint
var histograms [ ] HPoint
var prevSS * Series
inMatrix := make ( Matrix , 1 )
inArgs [ matrixArgIndex ] = inMatrix
enh := & EvalNodeHelper { Out : make ( Vector , 0 , 1 ) }
@ -1512,12 +1513,13 @@ func (ev *evaluator) eval(expr parser.Expr) (parser.Value, annotations.Annotatio
if len ( outVec ) > 0 {
if outVec [ 0 ] . H == nil {
if ss . Floats == nil {
ss . Floats = getFPointSlice ( numSteps )
ss . Floats = reuseOrGetFPointSlices ( prevSS , numSteps )
}
ss . Floats = append ( ss . Floats , FPoint { F : outVec [ 0 ] . F , T : ts } )
} else {
if ss . Histograms == nil {
ss . Histograms = getHPointSlice ( numSteps )
ss . Histograms = reuseOrGetHPointSlices ( prevSS , numSteps )
}
ss . Histograms = append ( ss . Histograms , HPoint { H : outVec [ 0 ] . H , T : ts } )
}
@ -1526,9 +1528,11 @@ func (ev *evaluator) eval(expr parser.Expr) (parser.Value, annotations.Annotatio
it . ReduceDelta ( stepRange )
}
histSamples := totalHPointSize ( ss . Histograms )
if len ( ss . Floats ) + histSamples > 0 {
if ev . currentSamples + len ( ss . Floats ) + histSamples <= ev . maxSamples {
mat = append ( mat , ss )
prevSS = & mat [ len ( mat ) - 1 ]
ev . currentSamples += len ( ss . Floats ) + histSamples
} else {
ev . error ( ErrTooManySamples ( env ) )
@ -1678,6 +1682,7 @@ func (ev *evaluator) eval(expr parser.Expr) (parser.Value, annotations.Annotatio
ev . error ( errWithWarnings { fmt . Errorf ( "expanding series: %w" , err ) , ws } )
}
mat := make ( Matrix , 0 , len ( e . Series ) )
var prevSS * Series
it := storage . NewMemoizedEmptyIterator ( durationMilliseconds ( ev . lookbackDelta ) )
var chkIter chunkenc . Iterator
for i , s := range e . Series {
@ -1697,14 +1702,14 @@ func (ev *evaluator) eval(expr parser.Expr) (parser.Value, annotations.Annotatio
if ev . currentSamples < ev . maxSamples {
if h == nil {
if ss . Floats == nil {
ss . Floats = getFPointSlice ( numSteps )
ss . Floats = reuseOrGetFPointSlices ( prevSS , numSteps )
}
ss . Floats = append ( ss . Floats , FPoint { F : f , T : ts } )
ev . currentSamples ++
ev . samplesStats . IncrementSamplesAtStep ( step , 1 )
} else {
if ss . Histograms == nil {
ss . Histograms = getHPointSlice ( numSteps )
ss . Histograms = reuseOrGetHPointSlices ( prevSS , numSteps )
}
point := HPoint { H : h , T : ts }
ss . Histograms = append ( ss . Histograms , point )
@ -1720,6 +1725,7 @@ func (ev *evaluator) eval(expr parser.Expr) (parser.Value, annotations.Annotatio
if len ( ss . Floats ) + len ( ss . Histograms ) > 0 {
mat = append ( mat , ss )
prevSS = & mat [ len ( mat ) - 1 ]
}
}
ev . samplesStats . UpdatePeak ( ev . currentSamples )
@ -1840,6 +1846,30 @@ func (ev *evaluator) eval(expr parser.Expr) (parser.Value, annotations.Annotatio
panic ( fmt . Errorf ( "unhandled expression of type: %T" , expr ) )
}
// reuseOrGetFPointSlices reuses the space from previous slice to create new slice if the former has lots of room.
// The previous slices capacity is adjusted so when it is re-used from the pool it doesn't overflow into the new one.
func reuseOrGetHPointSlices ( prevSS * Series , numSteps int ) ( r [ ] HPoint ) {
if prevSS != nil && cap ( prevSS . Histograms ) - 2 * len ( prevSS . Histograms ) > 0 {
r = prevSS . Histograms [ len ( prevSS . Histograms ) : ]
prevSS . Histograms = prevSS . Histograms [ 0 : len ( prevSS . Histograms ) : len ( prevSS . Histograms ) ]
return
}
return getHPointSlice ( numSteps )
}
// reuseOrGetFPointSlices reuses the space from previous slice to create new slice if the former has lots of room.
// The previous slices capacity is adjusted so when it is re-used from the pool it doesn't overflow into the new one.
func reuseOrGetFPointSlices ( prevSS * Series , numSteps int ) ( r [ ] FPoint ) {
if prevSS != nil && cap ( prevSS . Floats ) - 2 * len ( prevSS . Floats ) > 0 {
r = prevSS . Floats [ len ( prevSS . Floats ) : ]
prevSS . Floats = prevSS . Floats [ 0 : len ( prevSS . Floats ) : len ( prevSS . Floats ) ]
return
}
return getFPointSlice ( numSteps )
}
func ( ev * evaluator ) rangeEvalTimestampFunctionOverVectorSelector ( vs * parser . VectorSelector , call FunctionCall , e * parser . Call ) ( parser . Value , annotations . Annotations ) {
ws , err := checkAndExpandSeriesSet ( ev . ctx , vs )
if err != nil {