this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

internal/core/adt: use pointers for snapshot and result in nodeContext

These fields are only used in evalv2's disjunction algorithm,
so they are entirely unused in evalv3, the current default.
Given how often nodeContext structs are allocated,
this helps reduce the memory usage of the new allocator.

│ old │ new │
│ sec/op │ sec/op vs base │
VetAutomata 724.0m ± 13% 674.2m ± 9% -6.88% (p=0.050 n=8)

│ old │ new │
│ B/op │ B/op vs base │
VetAutomata 700.7Mi ± 0% 631.9Mi ± 0% -9.81% (p=0.000 n=8)

│ old │ new │
│ allocs/op │ allocs/op vs base │
VetAutomata 4.478M ± 0% 4.478M ± 0% ~ (p=0.316 n=8)

Performance on evalv2 is unaffected; adt.TestEvalV2 still takes 3.9s,
and Unity on evalv2 shows noise in the 0-5% range.
Unity on evalv3 shows improvements between 0 and 10% for wall times
as well as for Go.AllocBytes counters.

Updates #3334.

Signed-off-by: Daniel Martí <mvdan@mvdan.cc>
Change-Id: Idab308cb88980b9618c9c4164fae41b870442bd9
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1217121
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>
Reviewed-by: Marcel van Lohuizen <mpvl@gmail.com>
Unity-Result: CUE porcuepine <cue.porcuepine@gmail.com>

+18 -16
+12 -9
internal/core/adt/disjunct.go
··· 166 166 // save nodeContext. 167 167 168 168 if recursive || len(n.disjunctions) > 0 { 169 - n.snapshot = clone(*n.node) 169 + n.snapshot = clone(n.node) 170 170 } else { 171 - n.snapshot = *n.node 171 + n.snapshot = n.node 172 172 } 173 173 174 174 defaultOffset := len(n.usedDefault) ··· 206 206 207 207 if recursive { 208 208 *n = m 209 - n.result = *n.node // XXX: n.result = snapshotVertex(n.node)? 210 - n.node = &n.result 209 + nn := *n.node 210 + n.result = &nn // XXX: n.result = snapshotVertex(n.node)? 211 + n.node = n.result 211 212 n.disjuncts = append(n.disjuncts, n) 212 213 } 213 214 if n.node.BaseValue == nil { ··· 246 247 case d.expr != nil: 247 248 for _, v := range d.expr.Values { 248 249 cn := dn.clone() 249 - *cn.node = clone(dn.snapshot) 250 + *cn.node = *clone(dn.snapshot) 250 251 cn.node.state = cn 251 252 252 253 c := MakeConjunct(d.env, v.Val, d.cloneID) ··· 271 272 case d.value != nil: 272 273 for i, v := range d.value.Values { 273 274 cn := dn.clone() 274 - *cn.node = clone(dn.snapshot) 275 + *cn.node = *clone(dn.snapshot) 275 276 cn.node.state = cn 276 277 277 278 cn.addValueConjunct(d.env, v, d.cloneID) ··· 425 426 if last { 426 427 flags |= IgnoreOptional 427 428 } 428 - if Equal(n.ctx, &v.result, &d.result, flags) { 429 + if Equal(n.ctx, v.result, d.result, flags) { 429 430 m := maybeDefault 430 431 for _, u := range d.usedDefault { 431 432 m = combineDefault(m, u.nestedMode) ··· 497 498 // and can be used as is, or Structs is assumed to not yet be computed at the 498 499 // time that a clone is needed and must be nil. Conjuncts no longer needed and 499 500 // can become nil. All other fields can be copied shallowly. 500 - func clone(v Vertex) Vertex { 501 + func clone(v *Vertex) *Vertex { 502 + v2 := *v 503 + v = &v2 501 504 v.state = nil 502 505 if a := v.Arcs; len(a) > 0 { 503 506 v.Arcs = make([]*Vertex, len(a)) ··· 515 518 a := *arc 516 519 a.state = arc.state.clone() 517 520 a.state.node = &a 518 - a.state.snapshot = clone(a) 521 + a.state.snapshot = clone(arc) 519 522 v.Arcs[i] = &a 520 523 } 521 524 }
+6 -7
internal/core/adt/eval.go
··· 308 308 switch len(n.disjuncts) { 309 309 case 0: 310 310 case 1: 311 - x := n.disjuncts[0].result 311 + x := *n.disjuncts[0].result 312 312 x.state = nil 313 313 x.cyclicReferences = n.node.cyclicReferences 314 314 *v = x ··· 973 973 p := 0 974 974 hasDefaults := false 975 975 for i, x := range n.disjuncts { 976 - v := new(Vertex) 977 - *v = x.result 976 + v := *x.result 978 977 v.state = nil 979 978 switch x.defaultMode { 980 979 case isDefault: 981 980 a[i] = a[p] 982 - a[p] = v 981 + a[p] = &v 983 982 p++ 984 983 hasDefaults = true 985 984 ··· 987 986 hasDefaults = true 988 987 fallthrough 989 988 case maybeDefault: 990 - a[i] = v 989 + a[i] = &v 991 990 } 992 991 } 993 992 // TODO: disambiguate based on concrete values. ··· 1102 1101 hasDisjunction bool 1103 1102 1104 1103 // snapshot holds the last value of the vertex before calling postDisjunct. 1105 - snapshot Vertex 1104 + snapshot *Vertex 1106 1105 1107 1106 // Result holds the last evaluated value of the vertex after calling 1108 1107 // postDisjunct. 1109 - result Vertex 1108 + result *Vertex 1110 1109 } 1111 1110 1112 1111 type conjunct struct {