Skip to content

Commit 42b9bd4

Browse files
authored
Pin Pieces if we can determine they will split just by their children. (#1378)
Pin Pieces if we can determine they will split just by their children. If, for example, the elements inside a ListPiece are longer than the page width when you add up all of their characters, then the ListPiece will definitely split. But the Solver will try every possible way to *not* split that Piece and waste a ton of time doing so. In particular, since the Solver reaches outermost Pieces first, it will fully explore the entire Solution tree where those don't split before finally giving up and letting them split. But the outmost Pieces also have the largest number of Solutions that can be derived from them, so the Solver gets stuck exploring entire huge pointless branches. That's unnecessary because in some cases it's obvious that a Piece will split just because of how big it's contents are. Assuming an 80-character width, a ListPiece for a collection literal is *definitely* going to split if it's contents are >80 characters long. We don't need the Solver to figure that out. This PR adds an optimization where before solving, we ask each Piece if it can be pinned to a state based just on the length of its children and whether there are any newlines in them. Then, for ListPiece and InfixPiece, we implement that optimization. Also, added a bunch of benchmarks that validate this optimization for various syntax using those pieces. With this optimization, the new formatter is now only about 30% slower than the old one on the large benchmark. (It's faster than the old formatter and slower for some of the other various benchmarks.) That's at the point where we can start looking for constant-time optimizations. \o/
1 parent 7d5dcfc commit 42b9bd4

18 files changed

+4969
-505
lines changed

benchmark/case/collection_large.expect

Lines changed: 511 additions & 0 deletions
Large diffs are not rendered by default.

benchmark/case/collection_large.expect_short

Lines changed: 511 additions & 0 deletions
Large diffs are not rendered by default.

benchmark/case/collection_large.stmt

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
40 columns |
2+
// Test collection literals.
3+
[
4+
[
5+
[
6+
[list + element1, list + element2, list + element3],
7+
{set + element1, set + element2, set + element3},
8+
{map + key1: map + value1, map + key2: map + value2},
9+
(record + field1, record + field2, record + field3),
10+
(name1: record + field1, name2: record + field2),
11+
],
12+
{
13+
[list + element1, list + element2, list + element3],
14+
{set + element1, set + element2, set + element3},
15+
{map + key1: map + value1, map + key2: map + value2},
16+
(record + field1, record + field2, record + field3),
17+
(name1: record + field1, name2: record + field2),
18+
},
19+
{
20+
key1: [list + element1, list + element2, list + element3],
21+
key2: {set + element1, set + element2, set + element3},
22+
key3: {map + key1: map + value1, map + key2: map + value2},
23+
key4: (record + field1, record + field2, record + field3),
24+
key5: (name1: record + field1, name2: record + field2),
25+
},
26+
(
27+
[list + element1, list + element2, list + element3],
28+
{set + element1, set + element2, set + element3},
29+
{map + key1: map + value1, map + key2: map + value2},
30+
(record + field1, record + field2, record + field3),
31+
(name1: record + field1, name2: record + field2),
32+
),
33+
(
34+
field1: [list + element1, list + element2, list + element3],
35+
field2: {set + element1, set + element2, set + element3},
36+
field3: {map + key1: map + value1, map + key2: map + value2},
37+
field4: (record + field1, record + field2, record + field3),
38+
field5: (name1: record + field1, name2: record + field2),
39+
),
40+
],
41+
{
42+
[
43+
[list + element1, list + element2, list + element3],
44+
{set + element1, set + element2, set + element3},
45+
{map + key1: map + value1, map + key2: map + value2},
46+
(record + field1, record + field2, record + field3),
47+
(name1: record + field1, name2: record + field2),
48+
],
49+
{
50+
[list + element1, list + element2, list + element3],
51+
{set + element1, set + element2, set + element3},
52+
{map + key1: map + value1, map + key2: map + value2},
53+
(record + field1, record + field2, record + field3),
54+
(name1: record + field1, name2: record + field2),
55+
},
56+
{
57+
key1: [list + element1, list + element2, list + element3],
58+
key2: {set + element1, set + element2, set + element3},
59+
key3: {map + key1: map + value1, map + key2: map + value2},
60+
key4: (record + field1, record + field2, record + field3),
61+
key5: (name1: record + field1, name2: record + field2),
62+
},
63+
(
64+
[list + element1, list + element2, list + element3],
65+
{set + element1, set + element2, set + element3},
66+
{map + key1: map + value1, map + key2: map + value2},
67+
(record + field1, record + field2, record + field3),
68+
(name1: record + field1, name2: record + field2),
69+
),
70+
(
71+
field1: [list + element1, list + element2, list + element3],
72+
field2: {set + element1, set + element2, set + element3},
73+
field3: {map + key1: map + value1, map + key2: map + value2},
74+
field4: (record + field1, record + field2, record + field3),
75+
field5: (name1: record + field1, name2: record + field2),
76+
),
77+
},
78+
{
79+
key1: [
80+
[list + element1, list + element2, list + element3],
81+
{set + element1, set + element2, set + element3},
82+
{map + key1: map + value1, map + key2: map + value2},
83+
(record + field1, record + field2, record + field3),
84+
(name1: record + field1, name2: record + field2),
85+
],
86+
key2: {
87+
[list + element1, list + element2, list + element3],
88+
{set + element1, set + element2, set + element3},
89+
{map + key1: map + value1, map + key2: map + value2},
90+
(record + field1, record + field2, record + field3),
91+
(name1: record + field1, name2: record + field2),
92+
},
93+
key3: {
94+
key1: [list + element1, list + element2, list + element3],
95+
key2: {set + element1, set + element2, set + element3},
96+
key3: {map + key1: map + value1, map + key2: map + value2},
97+
key4: (record + field1, record + field2, record + field3),
98+
key5: (name1: record + field1, name2: record + field2),
99+
},
100+
key4: (
101+
[list + element1, list + element2, list + element3],
102+
{set + element1, set + element2, set + element3},
103+
{map + key1: map + value1, map + key2: map + value2},
104+
(record + field1, record + field2, record + field3),
105+
(name1: record + field1, name2: record + field2),
106+
),
107+
key5: (
108+
field1: [list + element1, list + element2, list + element3],
109+
field2: {set + element1, set + element2, set + element3},
110+
field3: {map + key1: map + value1, map + key2: map + value2},
111+
field4: (record + field1, record + field2, record + field3),
112+
field5: (name1: record + field1, name2: record + field2),
113+
),
114+
},
115+
(
116+
[
117+
[list + element1, list + element2, list + element3],
118+
{set + element1, set + element2, set + element3},
119+
{map + key1: map + value1, map + key2: map + value2},
120+
(record + field1, record + field2, record + field3),
121+
(name1: record + field1, name2: record + field2),
122+
],
123+
{
124+
[list + element1, list + element2, list + element3],
125+
{set + element1, set + element2, set + element3},
126+
{map + key1: map + value1, map + key2: map + value2},
127+
(record + field1, record + field2, record + field3),
128+
(name1: record + field1, name2: record + field2),
129+
},
130+
{
131+
key1: [list + element1, list + element2, list + element3],
132+
key2: {set + element1, set + element2, set + element3},
133+
key3: {map + key1: map + value1, map + key2: map + value2},
134+
key4: (record + field1, record + field2, record + field3),
135+
key5: (name1: record + field1, name2: record + field2),
136+
},
137+
(
138+
[list + element1, list + element2, list + element3],
139+
{set + element1, set + element2, set + element3},
140+
{map + key1: map + value1, map + key2: map + value2},
141+
(record + field1, record + field2, record + field3),
142+
(name1: record + field1, name2: record + field2),
143+
),
144+
(
145+
field1: [list + element1, list + element2, list + element3],
146+
field2: {set + element1, set + element2, set + element3},
147+
field3: {map + key1: map + value1, map + key2: map + value2},
148+
field4: (record + field1, record + field2, record + field3),
149+
field5: (name1: record + field1, name2: record + field2),
150+
),
151+
),
152+
];

0 commit comments

Comments
 (0)