diff --git a/pkg/traceql/ast_execute.go b/pkg/traceql/ast_execute.go index de434e3cd55..0ee6ad0c87c 100644 --- a/pkg/traceql/ast_execute.go +++ b/pkg/traceql/ast_execute.go @@ -336,7 +336,7 @@ func (o *BinaryOperation) execute(span Span) (Static, error) { } if recording { - o.b.Finish(0) + o.b.Finish(leftBranch) } // Look for cases where we don't even need to evalulate the RHS @@ -366,7 +366,7 @@ func (o *BinaryOperation) execute(span Span) (Static, error) { } if recording { - o.b.Finish(1) + o.b.Finish(rightBranch) } // Ensure the resolved types are still valid @@ -449,39 +449,40 @@ func (o *BinaryOperation) execute(span Span) (Static, error) { rhsB, _ := rhs.Bool() if recording { - if done := o.b.Sampled(); done { - if o.b.OptimalBranch() == 1 { - // RHS is the optimal starting branch, - // so swap the elements now. - o.LHS, o.RHS = o.RHS, o.LHS - } - } - } - - switch o.Op { - case OpAnd: - if recording { + switch o.Op { + case OpAnd: if !lhsB { // Record cost of wasted rhs execution - o.b.Penalize(1) + o.b.Penalize(rightBranch) } if !rhsB { // Record cost of wasted lhs execution - o.b.Penalize(0) + o.b.Penalize(leftBranch) } - } - return NewStaticBool(lhsB && rhsB), nil - case OpOr: - if recording { + case OpOr: if rhsB { // Record cost of wasted lhs execution - o.b.Penalize(0) + o.b.Penalize(rightBranch) } if lhsB { // Record cost of wasated rhs execution - o.b.Penalize(1) + o.b.Penalize(leftBranch) } } + + if done := o.b.Sampled(); done { + if o.b.OptimalBranch() == rightBranch { + // RHS is the optimal starting branch, + // so swap the elements now. + o.LHS, o.RHS = o.RHS, o.LHS + } + } + } + + switch o.Op { + case OpAnd: + return NewStaticBool(lhsB && rhsB), nil + case OpOr: return NewStaticBool(lhsB || rhsB), nil } } diff --git a/pkg/traceql/util.go b/pkg/traceql/util.go index cd4890a5dea..90a982d2cd2 100644 --- a/pkg/traceql/util.go +++ b/pkg/traceql/util.go @@ -84,6 +84,11 @@ func (b *bucketSet) addAndTest(i int) bool { return false } +const ( + leftBranch = 0 + rightBranch = 1 +) + type branchOptimizer struct { start time.Time last []time.Duration