Skip to content

Commit a03ed2e

Browse files
committed
internal/core/adt: more pruning in partial disjunction check
In a partial conjunction check, equality for uncompleted tasks need to be verified to be equal. In many cases tasks will have completed before a disjunction is checked. This is especially true for tasks that result from a reference like `string`. Previously, the implementation ignored the scheduler's taskPos field, thereby considering any task to be not completed, causing many disambiguation opportunities to be missed. The new implementation fast tracks the common case when both disjuncts have all tasks completed. Furthermore, it only compares tasks that are not done yet. This adds one nodeCounter issue, which is related to the embedded identifier. This will need to be addressed elsewhere. Fixes #3610 Signed-off-by: Marcel van Lohuizen <[email protected]> Change-Id: Ib3a5830d415e9afd74e8c96b6a0b97383c53218c Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1205400 Unity-Result: CUE porcuepine <[email protected]> Reviewed-by: Matthew Sackman <[email protected]> TryBot-Result: CUEcueckoo <[email protected]>
1 parent 6d15591 commit a03ed2e

File tree

4 files changed

+76
-38
lines changed

4 files changed

+76
-38
lines changed

Diff for: cue/testdata/benchmarks/disjunctelim.txtar

+57-24
Original file line numberDiff line numberDiff line change
@@ -25,47 +25,61 @@ list: [1] | [2] | [3] | [4] // 151 conjuncts; 68 disjuncts (+33; +16)
2525
list: [1] | [2] | [3] | [4] // 184 conjuncts; 84 disjuncts (+33; +16)
2626
list: [1] | [2] | [3] | [4] // 217 conjuncts; 100 disjuncts (+33; +16)
2727

28+
issue3610: {
29+
// Ensure disjuncts are disambiguated. The string field here is a reference
30+
// and causes a task to be added. Ensure that, for instance, disjuncts
31+
// >"b" and (>"b" & string) get equated when at least the task has
32+
// completed.
33+
#a
34+
#a: <"a" | >"b" | string
35+
#a: <"a" | >"b" | string // conjuncts 127 disjuncts 120
36+
#a: <"a" | >"b" | string // conjuncts 219 disjuncts 210 (+92; +90)
37+
#a: <"a" | >"b" | string // conjuncts 311 disjuncts 300 (+92; +90)
38+
#a: <"a" | >"b" | string // conjuncts 403 disjuncts 390 (+92; +90)
39+
#a: <"a" | >"b" | string // conjuncts 495 disjuncts 480 (+92; +90)
40+
}
41+
2842
-- out/evalalpha/stats --
29-
Leaks: 182
30-
Freed: 90
31-
Reused: 90
32-
Allocs: 182
43+
Leaks: 572
44+
Freed: 230
45+
Reused: 230
46+
Allocs: 572
3347
Retain: 0
3448

35-
Unifications: 20
36-
Conjuncts: 327
37-
Disjuncts: 138
49+
Unifications: 22
50+
Conjuncts: 825
51+
Disjuncts: 618
3852
-- diff/-out/evalalpha/stats<==>+out/eval/stats --
3953
diff old new
4054
--- old
4155
+++ new
4256
@@ -1,9 +1,9 @@
4357
-Leaks: 0
44-
-Freed: 269
45-
-Reused: 258
58+
-Freed: 367
59+
-Reused: 356
4660
-Allocs: 11
47-
+Leaks: 182
48-
+Freed: 90
49-
+Reused: 90
50-
+Allocs: 182
61+
+Leaks: 572
62+
+Freed: 230
63+
+Reused: 230
64+
+Allocs: 572
5165
Retain: 0
5266

53-
-Unifications: 131
54-
-Conjuncts: 755
55-
-Disjuncts: 269
56-
+Unifications: 20
57-
+Conjuncts: 327
58-
+Disjuncts: 138
67+
-Unifications: 133
68+
-Conjuncts: 866
69+
-Disjuncts: 367
70+
+Unifications: 22
71+
+Conjuncts: 825
72+
+Disjuncts: 618
5973
-- out/eval/stats --
6074
Leaks: 0
61-
Freed: 269
62-
Reused: 258
75+
Freed: 367
76+
Reused: 356
6377
Allocs: 11
6478
Retain: 0
6579

66-
Unifications: 131
67-
Conjuncts: 755
68-
Disjuncts: 269
80+
Unifications: 133
81+
Conjuncts: 866
82+
Disjuncts: 367
6983
-- out/eval --
7084
(struct){
7185
pat: (struct){ |((struct){
@@ -81,6 +95,16 @@ Disjuncts: 269
8195
}, (#list){
8296
0: (int){ 4 }
8397
}) }
98+
issue3610: (string){ |((string){
99+
<"a"
100+
#a: (string){ |((string){ <"a" }, (string){ >"b" }, (string){ string }) }
101+
}, (string){
102+
>"b"
103+
#a: (string){ |((string){ <"a" }, (string){ >"b" }, (string){ string }) }
104+
}, (string){
105+
string
106+
#a: (string){ |((string){ <"a" }, (string){ >"b" }, (string){ string }) }
107+
}) }
84108
}
85109
-- out/compile --
86110
--- in.cue
@@ -198,4 +222,13 @@ Disjuncts: 269
198222
]|[
199223
4,
200224
])
225+
issue3610: {
226+
〈0;#a〉
227+
#a: (<"a"|>"b"|string)
228+
#a: (<"a"|>"b"|string)
229+
#a: (<"a"|>"b"|string)
230+
#a: (<"a"|>"b"|string)
231+
#a: (<"a"|>"b"|string)
232+
#a: (<"a"|>"b"|string)
233+
}
201234
}

Diff for: cue/testdata/eval/conjuncts.txtar

+8-8
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,15 @@ issue2355: {
6969
}
7070

7171
-- out/evalalpha/stats --
72-
Leaks: 192
72+
Leaks: 188
7373
Freed: 24
7474
Reused: 24
75-
Allocs: 192
75+
Allocs: 188
7676
Retain: 0
7777

7878
Unifications: 43
79-
Conjuncts: 352
80-
Disjuncts: 126
79+
Conjuncts: 350
80+
Disjuncts: 124
8181
-- out/evalalpha --
8282
Errors:
8383
param: conflicting values "foo" and [{}] (mismatched types string and list):
@@ -168,18 +168,18 @@ diff old new
168168
-Reused: 59
169169
-Allocs: 18
170170
-Retain: 22
171-
+Leaks: 192
171+
+Leaks: 188
172172
+Freed: 24
173173
+Reused: 24
174-
+Allocs: 192
174+
+Allocs: 188
175175
+Retain: 0
176176

177177
-Unifications: 45
178178
-Conjuncts: 135
179179
-Disjuncts: 86
180180
+Unifications: 43
181-
+Conjuncts: 352
182-
+Disjuncts: 126
181+
+Conjuncts: 350
182+
+Disjuncts: 124
183183
-- diff/-out/evalalpha<==>+out/eval --
184184
diff old new
185185
--- old

Diff for: internal/core/adt/disjunct2.go

+10-6
Original file line numberDiff line numberDiff line change
@@ -573,10 +573,12 @@ outer:
573573
}
574574
}
575575
}
576-
if len(xn.tasks) != len(x.tasks) {
577-
continue
576+
if len(xn.tasks) != xn.taskPos || len(x.tasks) != x.taskPos {
577+
if len(xn.tasks) != len(x.tasks) {
578+
continue
579+
}
578580
}
579-
for i, t := range xn.tasks {
581+
for i, t := range xn.tasks[xn.taskPos:] {
580582
s := x.tasks[i]
581583
if s.x != t.x || s.id.cc != t.id.cc {
582584
continue outer
@@ -735,8 +737,10 @@ func isEqualNodeValue(x, y *nodeContext) bool {
735737
if len(x.checks) != len(y.checks) {
736738
return false
737739
}
738-
if len(x.tasks) != len(y.tasks) {
739-
return false
740+
if len(x.tasks) != x.taskPos || len(y.tasks) != y.taskPos {
741+
if len(x.tasks) != len(y.tasks) {
742+
return false
743+
}
740744
}
741745

742746
if !isEqualValue(x.ctx, x.lowerBound, y.lowerBound) {
@@ -754,7 +758,7 @@ func isEqualNodeValue(x, y *nodeContext) bool {
754758
}
755759
}
756760

757-
for i, t := range x.tasks {
761+
for i, t := range x.tasks[x.taskPos:] {
758762
s := y.tasks[i]
759763
if s.x != t.x {
760764
return false

Diff for: internal/core/adt/eval_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ var needFix = map[string]string{
7777
// TODO: These counters should all go to zero.
7878
var skipDebugDepErrors = map[string]int{
7979
"benchmarks/issue1684": 16,
80+
"benchmarks/disjunctelim": 1,
8081
"builtins/default": 1,
8182
"compile/scope": 1,
8283
"comprehensions/pushdown": 3,

0 commit comments

Comments
 (0)