Skip to content

Commit 28f8d47

Browse files
committed
internal/core/adt: performance: improve lists disambiguation
The equality used in disjunction uses StructLits identity for some elimination. However, as lists initially don't have those associated these have to be created dynamically. This change ensurse a unique StructLit is associated with each list so that lists that are trivially equal can be identified as such. This doesn't address the below issues completely (there are better solutions), but in these particular cases it does improve performance considerably. Issue #758 Issue #1044 Change-Id: I5d3080aa6503584ed26563f24b68de70b446fe1b Signed-off-by: Marcel van Lohuizen <[email protected]> Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/532656 Unity-Result: CUEcueckoo <[email protected]> TryBot-Result: CUEcueckoo <[email protected]> Reviewed-by: Marcel van Lohuizen <[email protected]>
1 parent a15720b commit 28f8d47

File tree

3 files changed

+231
-2
lines changed

3 files changed

+231
-2
lines changed
+223
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
#Issue: 758
2+
#Issue: 1044
3+
4+
-- in.cue --
5+
A: #Task
6+
B: #steps: #Script & { mount: [A] }
7+
C: #steps: #Script & { mount: [B] }
8+
9+
#Script: { mount: [...#Task] }
10+
11+
#Task: {
12+
// Without the proper constructs, repeating the below results
13+
// in exponential runtime.
14+
#ref
15+
#ref
16+
_ | {}
17+
_ | {}
18+
#steps: #Script
19+
...
20+
}
21+
22+
#ref: {a:1} | {b:2}
23+
-- out/eval --
24+
(struct){
25+
A: (#struct){ |((#struct){
26+
#steps: (#struct){
27+
mount: (list){
28+
}
29+
}
30+
a: (int){ 1 }
31+
}, (#struct){
32+
#steps: (#struct){
33+
mount: (list){
34+
}
35+
}
36+
a: (int){ 1 }
37+
b: (int){ 2 }
38+
}, (#struct){
39+
#steps: (#struct){
40+
mount: (list){
41+
}
42+
}
43+
b: (int){ 2 }
44+
}) }
45+
B: (struct){
46+
#steps: (#struct){
47+
mount: (#list){
48+
0: (#struct){ |((#struct){
49+
#steps: (#struct){
50+
mount: (list){
51+
}
52+
}
53+
a: (int){ 1 }
54+
}, (#struct){
55+
#steps: (#struct){
56+
mount: (list){
57+
}
58+
}
59+
a: (int){ 1 }
60+
b: (int){ 2 }
61+
}, (#struct){
62+
#steps: (#struct){
63+
mount: (list){
64+
}
65+
}
66+
b: (int){ 2 }
67+
}) }
68+
}
69+
}
70+
}
71+
C: (struct){
72+
#steps: (#struct){
73+
mount: (#list){
74+
0: (#struct){ |((#struct){
75+
#steps: (#struct){
76+
mount: (#list){
77+
0: (#struct){ |((#struct){
78+
#steps: (#struct){
79+
mount: (list){
80+
}
81+
}
82+
a: (int){ 1 }
83+
}, (#struct){
84+
#steps: (#struct){
85+
mount: (list){
86+
}
87+
}
88+
a: (int){ 1 }
89+
b: (int){ 2 }
90+
}, (#struct){
91+
#steps: (#struct){
92+
mount: (list){
93+
}
94+
}
95+
b: (int){ 2 }
96+
}) }
97+
}
98+
}
99+
a: (int){ 1 }
100+
}, (#struct){
101+
#steps: (#struct){
102+
mount: (#list){
103+
0: (#struct){ |((#struct){
104+
#steps: (#struct){
105+
mount: (list){
106+
}
107+
}
108+
a: (int){ 1 }
109+
}, (#struct){
110+
#steps: (#struct){
111+
mount: (list){
112+
}
113+
}
114+
a: (int){ 1 }
115+
b: (int){ 2 }
116+
}, (#struct){
117+
#steps: (#struct){
118+
mount: (list){
119+
}
120+
}
121+
b: (int){ 2 }
122+
}) }
123+
}
124+
}
125+
a: (int){ 1 }
126+
b: (int){ 2 }
127+
}, (#struct){
128+
#steps: (#struct){
129+
mount: (#list){
130+
0: (#struct){ |((#struct){
131+
#steps: (#struct){
132+
mount: (list){
133+
}
134+
}
135+
a: (int){ 1 }
136+
}, (#struct){
137+
#steps: (#struct){
138+
mount: (list){
139+
}
140+
}
141+
a: (int){ 1 }
142+
b: (int){ 2 }
143+
}, (#struct){
144+
#steps: (#struct){
145+
mount: (list){
146+
}
147+
}
148+
b: (int){ 2 }
149+
}) }
150+
}
151+
}
152+
b: (int){ 2 }
153+
}) }
154+
}
155+
}
156+
}
157+
#Script: (#struct){
158+
mount: (list){
159+
}
160+
}
161+
#Task: (#struct){ |((#struct){
162+
#steps: (#struct){
163+
mount: (list){
164+
}
165+
}
166+
a: (int){ 1 }
167+
}, (#struct){
168+
#steps: (#struct){
169+
mount: (list){
170+
}
171+
}
172+
a: (int){ 1 }
173+
b: (int){ 2 }
174+
}, (#struct){
175+
#steps: (#struct){
176+
mount: (list){
177+
}
178+
}
179+
b: (int){ 2 }
180+
}) }
181+
#ref: (#struct){ |((#struct){
182+
a: (int){ 1 }
183+
}, (#struct){
184+
b: (int){ 2 }
185+
}) }
186+
}
187+
-- out/compile --
188+
--- in.cue
189+
{
190+
A: 〈0;#Task〉
191+
B: {
192+
#steps: (〈1;#Script〉 & {
193+
mount: [
194+
〈3;A〉,
195+
]
196+
})
197+
}
198+
C: {
199+
#steps: (〈1;#Script〉 & {
200+
mount: [
201+
〈3;B〉,
202+
]
203+
})
204+
}
205+
#Script: {
206+
mount: [
207+
...〈2;#Task〉,
208+
]
209+
}
210+
#Task: {
211+
〈1;#ref〉
212+
〈1;#ref〉
213+
(_|{})
214+
(_|{})
215+
#steps: 〈1;#Script〉
216+
...
217+
}
218+
#ref: ({
219+
a: 1
220+
}|{
221+
b: 2
222+
})
223+
}

internal/core/adt/eval.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -2123,8 +2123,12 @@ outer:
21232123
continue
21242124
}
21252125

2126-
s := &StructLit{Decls: []Decl{l.elipsis}}
2127-
s.Init()
2126+
s := l.list.info
2127+
if s == nil {
2128+
s = &StructLit{Decls: []Decl{l.elipsis}}
2129+
s.Init()
2130+
l.list.info = s
2131+
}
21282132
info := n.node.AddStruct(s, l.env, l.id)
21292133

21302134
for _, arc := range elems[l.n:] {

internal/core/adt/expr.go

+2
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,8 @@ type ListLit struct {
280280

281281
// scalars, comprehensions, ...T
282282
Elems []Elem
283+
284+
info *StructLit // Shared closedness info.
283285
}
284286

285287
func (x *ListLit) Source() ast.Node {

0 commit comments

Comments
 (0)