blob: 6a9e92ea3cb9ed22f575e0355ea1c0c3e181638b [file] [log] [blame]
package stepfit
import (
"math"
"go.skia.org/infra/go/vec32"
)
const (
// The possible values for StepFit.Status are:
LOW = "Low"
HIGH = "High"
UNINTERESTING = "Uninteresting"
)
// StepFit stores information on the best Step Function fit on a trace.
//
// Used in ClusterSummary.
type StepFit struct {
// LeastSquares is the Least Squares error for a step function curve fit to the trace.
LeastSquares float32 `json:"least_squares"`
// TurningPoint is the index where the Step Function changes value.
TurningPoint int `json:"turning_point"`
// StepSize is the size of the step in the step function. Negative values
// indicate a step up, i.e. they look like a performance regression in the
// trace, as opposed to positive values which look like performance
// improvements.
StepSize float32 `json:"step_size"`
// The "Regression" value is calculated as Step Size / Least Squares Error.
//
// The better the fit the larger the number returned, because LSE
// gets smaller with a better fit. The higher the Step Size the
// larger the number returned.
Regression float32 `json:"regression"`
// Status of the cluster.
//
// Values can be "High", "Low", and "Uninteresting"
Status string `json:"status"`
}
// GetStepFitAtMid takes one []float32 trace and calculates and returns a StepFit.
//
// See StepFit for a description of the values being calculated.
func GetStepFitAtMid(trace []float32, interesting float32) *StepFit {
lse := float32(math.MaxFloat32)
stepSize := float32(-1.0)
turn := 0
i := len(trace) / 2
y0 := vec32.Mean(trace[:i])
y1 := vec32.Mean(trace[i:])
if y0 != y1 {
d := vec32.SSE(trace[:i], y0) + vec32.SSE(trace[i:], y1)
if d < lse {
lse = d
stepSize = (y0 - y1)
turn = i
}
}
lse = float32(math.Sqrt(float64(lse))) / float32(len(trace))
regression := stepSize / lse
status := UNINTERESTING
if regression > interesting {
status = LOW
} else if regression < -interesting {
status = HIGH
}
return &StepFit{
LeastSquares: lse,
StepSize: stepSize,
TurningPoint: turn,
Regression: regression,
Status: status,
}
}