mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-16 15:20:17 +00:00
Merge pull request #129749 from pohly/dra-cel-cost-estimate-during-validation
DRA: CEL cost estimate during validation
This commit is contained in:
commit
9635a253da
@ -43,6 +43,8 @@ func NewCache(maxCacheEntries int) *Cache {
|
|||||||
// GetOrCompile checks whether the cache already has a compilation result
|
// GetOrCompile checks whether the cache already has a compilation result
|
||||||
// and returns that if available. Otherwise it compiles, stores successful
|
// and returns that if available. Otherwise it compiles, stores successful
|
||||||
// results and returns the new result.
|
// results and returns the new result.
|
||||||
|
//
|
||||||
|
// Cost estimation is disabled.
|
||||||
func (c *Cache) GetOrCompile(expression string) CompilationResult {
|
func (c *Cache) GetOrCompile(expression string) CompilationResult {
|
||||||
// Compiling a CEL expression is expensive enough that it is cheaper
|
// Compiling a CEL expression is expensive enough that it is cheaper
|
||||||
// to lock a mutex than doing it several times in parallel.
|
// to lock a mutex than doing it several times in parallel.
|
||||||
@ -55,7 +57,7 @@ func (c *Cache) GetOrCompile(expression string) CompilationResult {
|
|||||||
return *cached
|
return *cached
|
||||||
}
|
}
|
||||||
|
|
||||||
expr := GetCompiler().CompileCELExpression(expression, Options{})
|
expr := GetCompiler().CompileCELExpression(expression, Options{DisableCostEstimation: true})
|
||||||
if expr.Error == nil {
|
if expr.Error == nil {
|
||||||
c.add(expression, &expr)
|
c.add(expression, &expr)
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ package cel
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -73,6 +74,11 @@ func TestCacheSemantic(t *testing.T) {
|
|||||||
if resultFalse == resultFalseAgain {
|
if resultFalse == resultFalseAgain {
|
||||||
t.Fatal("result of compiling `false` should have been evicted from the cache")
|
t.Fatal("result of compiling `false` should have been evicted from the cache")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cost estimation must be off (not needed by scheduler).
|
||||||
|
if resultFalseAgain.MaxCost != math.MaxUint64 {
|
||||||
|
t.Error("cost estimation should have been disabled, was enabled")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCacheConcurrency(t *testing.T) {
|
func TestCacheConcurrency(t *testing.T) {
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@ -120,6 +121,10 @@ type Options struct {
|
|||||||
|
|
||||||
// CostLimit allows overriding the default runtime cost limit [resourceapi.CELSelectorExpressionMaxCost].
|
// CostLimit allows overriding the default runtime cost limit [resourceapi.CELSelectorExpressionMaxCost].
|
||||||
CostLimit *uint64
|
CostLimit *uint64
|
||||||
|
|
||||||
|
// DisableCostEstimation can be set to skip estimating the worst-case CEL cost.
|
||||||
|
// If disabled or after an error, [CompilationResult.MaxCost] will be set to [math.Uint64].
|
||||||
|
DisableCostEstimation bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompileCELExpression returns a compiled CEL expression. It evaluates to bool.
|
// CompileCELExpression returns a compiled CEL expression. It evaluates to bool.
|
||||||
@ -133,6 +138,7 @@ func (c compiler) CompileCELExpression(expression string, options Options) Compi
|
|||||||
Detail: errorString,
|
Detail: errorString,
|
||||||
},
|
},
|
||||||
Expression: expression,
|
Expression: expression,
|
||||||
|
MaxCost: math.MaxUint64,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,10 +147,6 @@ func (c compiler) CompileCELExpression(expression string, options Options) Compi
|
|||||||
return resultError(fmt.Sprintf("unexpected error loading CEL environment: %v", err), apiservercel.ErrorTypeInternal)
|
return resultError(fmt.Sprintf("unexpected error loading CEL environment: %v", err), apiservercel.ErrorTypeInternal)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't have a SizeEstimator. The potential size of the input (= a
|
|
||||||
// device) is already declared in the definition of the environment.
|
|
||||||
estimator := c.newCostEstimator()
|
|
||||||
|
|
||||||
ast, issues := env.Compile(expression)
|
ast, issues := env.Compile(expression)
|
||||||
if issues != nil {
|
if issues != nil {
|
||||||
return resultError("compilation failed: "+issues.String(), apiservercel.ErrorTypeInvalid)
|
return resultError("compilation failed: "+issues.String(), apiservercel.ErrorTypeInvalid)
|
||||||
@ -176,15 +178,21 @@ func (c compiler) CompileCELExpression(expression string, options Options) Compi
|
|||||||
OutputType: ast.OutputType(),
|
OutputType: ast.OutputType(),
|
||||||
Environment: env,
|
Environment: env,
|
||||||
emptyMapVal: env.CELTypeAdapter().NativeToValue(map[string]any{}),
|
emptyMapVal: env.CELTypeAdapter().NativeToValue(map[string]any{}),
|
||||||
|
MaxCost: math.MaxUint64,
|
||||||
}
|
}
|
||||||
|
|
||||||
costEst, err := env.EstimateCost(ast, estimator)
|
if !options.DisableCostEstimation {
|
||||||
if err != nil {
|
// We don't have a SizeEstimator. The potential size of the input (= a
|
||||||
compilationResult.Error = &apiservercel.Error{Type: apiservercel.ErrorTypeInternal, Detail: "cost estimation failed: " + err.Error()}
|
// device) is already declared in the definition of the environment.
|
||||||
return compilationResult
|
estimator := c.newCostEstimator()
|
||||||
|
costEst, err := env.EstimateCost(ast, estimator)
|
||||||
|
if err != nil {
|
||||||
|
compilationResult.Error = &apiservercel.Error{Type: apiservercel.ErrorTypeInternal, Detail: "cost estimation failed: " + err.Error()}
|
||||||
|
return compilationResult
|
||||||
|
}
|
||||||
|
compilationResult.MaxCost = costEst.Max
|
||||||
}
|
}
|
||||||
|
|
||||||
compilationResult.MaxCost = costEst.Max
|
|
||||||
return compilationResult
|
return compilationResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user