Skip to content

Commit

Permalink
cue/stats: start reporting which CUE evaluator version was used
Browse files Browse the repository at this point in the history
Currently, when we select an evaluator version via CUE_EXPERIMENT
or via the Go API, it can be hard to really tell whether that version
is actually being used as part of evaluation. It may not be due to bugs,
for example, or because the way we are trying to select the version
doesn't actually work as intended, such as CUE_EXPERIMENT not affecting
the Go API until https://cuelang.org/cl/1202685.

As agreed with Marcel, a nice way for the evaluator to report the
version it used is the same way it already knows how to report other
information back to the user about the evaluation: CUE_STATS_FILE.

Note that it's currently not possible to collect these stats via the
exposed Go API, and that is a separate problem that we need to tackle.

Signed-off-by: Daniel Martí <[email protected]>
Change-Id: I6c868b44dde88ca491570c526d1e2f2f0503f1d1
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1202746
Reviewed-by: Marcel van Lohuizen <[email protected]>
TryBot-Result: CUEcueckoo <[email protected]>
  • Loading branch information
mvdan committed Oct 25, 2024
1 parent 52c4418 commit 956d746
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 0 deletions.
13 changes: 13 additions & 0 deletions cmd/cue/cmd/testdata/script/stats.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ env CUE_STATS_FILE=-
exec cue eval x.cue
cmp stderr out/stderr

# Check that EvalVersion reports the correct value.
env CUE_STATS_FILE=-
env CUE_EXPERIMENT=evalv3=0
exec cue eval x.cue
stderr -count=1 '"EvalVersion": 2,'
env CUE_EXPERIMENT=evalv3=1
exec cue eval x.cue
stderr -count=1 '"EvalVersion": 3,'

-- x.cue --
a: 1
b: 2
Expand All @@ -36,6 +45,7 @@ contents overwritten
-- out/stats.json --
{
"CUE": {
"EvalVersion": 2,
"Unifications": 4,
"Disjuncts": 6,
"Conjuncts": 8,
Expand All @@ -51,6 +61,7 @@ contents overwritten
}
-- out/stats.cue --
CUE: {
EvalVersion: 2
Unifications: 4
Disjuncts: 6
Conjuncts: 8
Expand All @@ -65,6 +76,7 @@ Go: {
}
-- out/stats.yaml --
CUE:
EvalVersion: 2
Unifications: 4
Disjuncts: 6
Conjuncts: 8
Expand All @@ -78,6 +90,7 @@ Go:
-- out/stderr --
{
"CUE": {
"EvalVersion": 2,
"Unifications": 4,
"Disjuncts": 6,
"Conjuncts": 8,
Expand Down
27 changes: 27 additions & 0 deletions cue/stats/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,23 @@ import (
"strings"
"sync"
"text/template"

"cuelang.org/go/internal"
)

// Counts holds counters for key events during a CUE evaluation.
//
// This is an experimental type and the contents may change without notice.
type Counts struct {
// Note that we can't use the public [cuecontext.EvalVersion] type
// as that would lead to an import cycle. We could use "int" but that's a bit odd.
// There's no harm in referencing an internal type in practice, given that
// the public type is a type alias for the internal type already.

// EvalVersion is the evaluator version which was used for the CUE evaluation,
// corresponding to one of the values under [cuelang.org/go/cue/cuecontext.EvalVersion].
EvalVersion internal.EvaluatorVersion

// Operation counters
//
// These counters account for several key operations.
Expand Down Expand Up @@ -69,6 +80,22 @@ type Counts struct {
// add checks on each of the operations.

func (c *Counts) Add(other Counts) {
switch v, vo := c.EvalVersion, other.EvalVersion; {
case v == internal.EvalVersionUnset:
// The first time we add evaluator counts, we record the evaluator version being used.
if vo == internal.EvalVersionUnset {
panic("the first call to Counts.Add must provide an evaluator version")
}
c.EvalVersion = vo
case v != vo:
// Any further evaluator counts being added must match the same evaluator version.
//
// TODO(mvdan): this is currently not possible to enforce, as we collect stats globally
// via [adt.AddStats] which includes stats from contexts created with different versions.
// We likely need to refactor the collection of stats so that it is not global first.

// panic(fmt.Sprintf("cannot mix evaluator versions in Counts.Add: %v vs %v", v, vo))
}
c.Unifications += other.Unifications
c.Conjuncts += other.Conjuncts
c.Disjuncts += other.Disjuncts
Expand Down
1 change: 1 addition & 0 deletions internal/core/adt/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ func New(v *Vertex, cfg *Config) *OpContext {
Format: cfg.Format,
vertex: v,
Version: version,
stats: stats.Counts{EvalVersion: version},
Config: flags,
taskContext: schedConfig,
}
Expand Down

0 comments on commit 956d746

Please sign in to comment.