Skip to content

Commit f197a88

Browse files
committed
[compiler] add fixture for optimization across scopes
Adds a fixture based on internal case where our current output is quite a bit more verbose than the original memoization. See the comment in the fixture for more about the heuristic we can apply. ghstack-source-id: d92c6d91700ad107882ba795e18416b3f587dae9 Pull Request resolved: #29998
1 parent 5aafec9 commit f197a88

File tree

2 files changed

+153
-0
lines changed

2 files changed

+153
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
2+
## Input
3+
4+
```javascript
5+
import { Stringify } from "shared-runtime";
6+
7+
function Component({ config }) {
8+
/**
9+
* The original memoization is optimal in the sense that it has
10+
* one output (the object) and one dependency (`config`). Both
11+
* the `a` and `b` functions will have to be recreated whenever
12+
* `config` changes, cascading to update the object.
13+
*
14+
* However, we currently only consider consecutive scopes for
15+
* merging, so we first see the `a` scope, then the `b` scope,
16+
* and see that the output of the `a` scope is used later -
17+
* so we don't merge these scopes, and so on.
18+
*
19+
* The more optimal thing would be to build a dependency graph
20+
* of scopes so that we can see the data flow is along the lines
21+
* of:
22+
*
23+
* config
24+
* / \
25+
* [a] [b]
26+
* \ /
27+
* [object]
28+
*
29+
* All the scopes (shown in []) are transitively dependent on
30+
* `config`, so they can be merged.
31+
*/
32+
const object = useMemo(() => {
33+
const a = (event) => {
34+
config?.onA?.(event);
35+
};
36+
37+
const b = (event) => {
38+
config?.onB?.(event);
39+
};
40+
41+
return {
42+
b,
43+
a,
44+
};
45+
}, [config]);
46+
47+
return <Stringify value={object} />;
48+
}
49+
50+
```
51+
52+
## Code
53+
54+
```javascript
55+
import { c as _c } from "react/compiler-runtime";
56+
import { Stringify } from "shared-runtime";
57+
58+
function Component(t0) {
59+
const $ = _c(9);
60+
const { config } = t0;
61+
let t1;
62+
let t2;
63+
if ($[0] !== config) {
64+
t2 = (event) => {
65+
config?.onA?.(event);
66+
};
67+
$[0] = config;
68+
$[1] = t2;
69+
} else {
70+
t2 = $[1];
71+
}
72+
const a = t2;
73+
let t3;
74+
if ($[2] !== config) {
75+
t3 = (event_0) => {
76+
config?.onB?.(event_0);
77+
};
78+
$[2] = config;
79+
$[3] = t3;
80+
} else {
81+
t3 = $[3];
82+
}
83+
const b = t3;
84+
let t4;
85+
if ($[4] !== b || $[5] !== a) {
86+
t4 = { b, a };
87+
$[4] = b;
88+
$[5] = a;
89+
$[6] = t4;
90+
} else {
91+
t4 = $[6];
92+
}
93+
t1 = t4;
94+
const object = t1;
95+
let t5;
96+
if ($[7] !== object) {
97+
t5 = <Stringify value={object} />;
98+
$[7] = object;
99+
$[8] = t5;
100+
} else {
101+
t5 = $[8];
102+
}
103+
return t5;
104+
}
105+
106+
```
107+
108+
### Eval output
109+
(kind: exception) Fixture not implemented
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { Stringify } from "shared-runtime";
2+
3+
function Component({ config }) {
4+
/**
5+
* The original memoization is optimal in the sense that it has
6+
* one output (the object) and one dependency (`config`). Both
7+
* the `a` and `b` functions will have to be recreated whenever
8+
* `config` changes, cascading to update the object.
9+
*
10+
* However, we currently only consider consecutive scopes for
11+
* merging, so we first see the `a` scope, then the `b` scope,
12+
* and see that the output of the `a` scope is used later -
13+
* so we don't merge these scopes, and so on.
14+
*
15+
* The more optimal thing would be to build a dependency graph
16+
* of scopes so that we can see the data flow is along the lines
17+
* of:
18+
*
19+
* config
20+
* / \
21+
* [a] [b]
22+
* \ /
23+
* [object]
24+
*
25+
* All the scopes (shown in []) are transitively dependent on
26+
* `config`, so they can be merged.
27+
*/
28+
const object = useMemo(() => {
29+
const a = (event) => {
30+
config?.onA?.(event);
31+
};
32+
33+
const b = (event) => {
34+
config?.onB?.(event);
35+
};
36+
37+
return {
38+
b,
39+
a,
40+
};
41+
}, [config]);
42+
43+
return <Stringify value={object} />;
44+
}

0 commit comments

Comments
 (0)