Skip to content

avoid repeated construction of cost tracker#1357

Merged
TristonianJones merged 1 commit into
cel-expr:masterfrom
pohly:cost-tracker-construction
Jul 2, 2026
Merged

avoid repeated construction of cost tracker#1357
TristonianJones merged 1 commit into
cel-expr:masterfrom
pohly:cost-tracker-construction

Conversation

@pohly

@pohly pohly commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Most fields in the CostTracker struct are only set once during construction. This takes a surprising amount of allocations, in particular for the overload map. Constructing the tracker once and cloning it for each evaluation avoids doing that work repeatedly.

In a Kubernetes benchmark exercising (among other things) CEL expression evaluation, the cumulative CPU time and allocs for Eval dropped from 3.87s to 1.99s resp. from 3.85G to 2.1G.

@TristonianJones

Copy link
Copy Markdown
Collaborator

/gcbrun

@TristonianJones

Copy link
Copy Markdown
Collaborator

@pohly Thanks for this change. Would you mind adding a test case that initiates initiates the cost tracking against a single compiled expression in a short loop to help prevent future regressions?

@pohly

pohly commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator Author

How can such a test verify that Eval doesn't call NewCostTracker again? Just calling Eval multiple times will not fail, with or without this patch.

@TristonianJones

Copy link
Copy Markdown
Collaborator

It's purely defensive ... more that if something changes in the cost tracker in the future to make sure we don't miss the updates to Clone. Currently the cost tests exercise single evaluation which probably won't hit the Clone case.

@pohly

pohly commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator Author

A single Eval always uses NewCostTracker (during program construction) followed by Clone (when the factory function is called). But it doesn't hurt to do Eval more than once to cover the scenario that Clone is called more than once - will add something.

Most fields in the CostTracker struct are only set once during
construction. This takes a surprising amount of allocations, in particular for
the overload map. Constructing the tracker once and cloning it for each
evaluation avoids doing that work repeatedly.

In a Kubernetes benchmark exercising (among other things) CEL expression
evaluation, the cumulative CPU time and allocs for Eval dropped from 3.87s to
1.99s resp. from 3.85G to 2.1G.
@pohly

pohly commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator Author

@TristonianJones: see https://github.com/cel-expr/cel-go/compare/c0b1db8e505326cc8463b8fed381c116a5ff9de1..164e53d3c0baad4da72f0df5400ef1526ffcc6a7 for unit tests.

computeCost in interpreter now exercises the NewCostTracker -> Clone code path, to detect early if Clone breaks. TestCostTrackingConsistentAcrossEvals in cel checks that repeated evaluation using the same program yields consistent costs.

@pohly

pohly commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator Author

@TristonianJones: gentle ping. Is there a chance to get this into a tagged release soonish? Code freeze deadline for Kubernetes is July 22nd, it would be great to bump cel-go there well in advance.

@TristonianJones

Copy link
Copy Markdown
Collaborator

/gcbrun

@TristonianJones TristonianJones merged commit fa16799 into cel-expr:master Jul 2, 2026
8 checks passed
pohly added a commit to pohly/kubernetes that referenced this pull request Jul 3, 2026
There may be some useful enhancements in
https://github.com/cel-expr/cel-go/releases/tag/v0.28.0, but primarily the goal
is to state up-to-date to simplify updating to a release which includes
cel-expr/cel-go#1357 because that is a relevant
performance improvement for how DRA uses CEL.

Updating to v0.28.1 is safe, in contrast to v0.28.0, because v0.28.1 includes
cel-expr/cel-go#1303 and therefore doesn't trigger
kubernetes#138334.
pohly added a commit to pohly/kubernetes that referenced this pull request Jul 3, 2026
There may be some useful enhancements in
https://github.com/cel-expr/cel-go/releases/tag/v0.28.0 and
https://github.com/cel-expr/cel-go/releases/tag/v0.29.0, but primarily the goal
is to get cel-expr/cel-go#1357 (included in v0.29.0)
because that is a relevant performance improvement for how DRA uses CEL.

Updating to >= v0.28.1 is safe, in contrast to v0.28.0, because v0.28.1 includes
cel-expr/cel-go#1303 and therefore doesn't trigger
kubernetes#138334.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants