10000 [Flight] Remove back pointers to the Response from the Chunks by sebmarkbage · Pull Request #33620 · facebook/react · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

[Flight] Remove back pointers to the Response from the Chunks #33620

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already o 10000 n GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 23, 2025

Conversation

sebmarkbage
Copy link
Collaborator
@sebmarkbage sebmarkbage commented Jun 23, 2025

This frees some memory that will be even more important in a follow up.

Currently, all ReactPromise instances hold onto their original Response. The Response holds onto all objects that were in that response since they're needed in case the parsed content ends up referring to an existing object. If everything you retain are plain objects then that's fine and the Response gets GC:ed, but if you're retaining a Promise itself then it holds onto the whole Response.

The only thing that needs this reference at all is a ResolvedModelChunk since it will lazily initialize e.g. by calling .then on itself and so we need to know where to find any sibling chunks it may refer to. However, we can just store the Response on the reason field for this particular state.

That way when all lazy values are touched and initialized the Response is freed. We also free up some memory by getting rid of the extra field.

It's the only one that needs it.
The reason field is free to be reused for this purpose.
@sebmarkbage sebmarkbage requested a review from unstubbable June 23, 2025 14:48
@github-actions github-actions bot added the React Core Team Opened by a member of the React Core Team label Jun 23, 2025
@react-sizebot
Copy link

Comparing: 2a911f2...70dcc16

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.js = 6.68 kB 6.68 kB = 1.83 kB 1.83 kB
oss-stable/react-dom/cjs/react-dom-client.production.js = 530.57 kB 530.57 kB = 93.67 kB 93.67 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 6.69 kB 6.69 kB = 1.83 kB 1.83 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js = 651.66 kB 651.66 kB = 114.78 kB 114.78 kB
facebook-www/ReactDOM-prod.classic.js = 674.81 kB 674.81 kB = 118.78 kB 118.78 kB
facebook-www/ReactDOM-prod.modern.js = 665.30 kB 665.30 kB = 117.19 kB 117.19 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js = 57.31 kB 57.19 kB = 11.66 kB 11.64 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js = 56.64 kB 56.52 kB = 11.57 kB 11.55 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js = 113.95 kB 113.69 kB = 20.99 kB 20.96 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js = 113.95 kB 113.69 kB = 20.99 kB 20.96 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.development.js = 112.62 kB 112.36 kB = 20.74 kB 20.71 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.development.js = 112.62 kB 112.36 kB = 20.74 kB 20.71 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js = 110.27 kB 110.00 kB = 20.51 kB 20.48 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js = 110.27 kB 110.00 kB = 20.51 kB 20.48 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js = 109.29 kB 109.02 kB = 20.39 kB 20.36 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js = 109.29 kB 109.02 kB = 20.39 kB 20.36 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js = 109.20 kB 108.93 kB = 20.36 kB 20.32 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js = 109.20 kB 108.93 kB = 20.36 kB 20.32 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js = 107.34 kB 107.08 kB = 20.02 kB 19.99 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js = 107.34 kB 107.08 kB = 20.02 kB 19.99 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js = 106.10 kB 105.84 kB = 19.88 kB 19.85 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js = 106.10 kB 105.84 kB = 19.88 kB 19.85 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js = 104.81 kB 104.55 kB = 19.57 kB 19.54 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js = 104.81 kB 104.55 kB = 19.57 kB 19.54 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js = 56.76 kB 56.62 kB = 11.57 kB 11.55 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js = 56.76 kB 56.62 kB = 11.57 kB 11.55 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js = 102.95 kB 102.68 kB = 19.30 kB 19.26 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js = 102.90 kB 102.63 kB = 19.28 kB 19.24 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js = 102.39 kB 102.12 kB = 19.17 kB 19.12 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js = 102.34 kB 102.07 kB = 19.14 kB 19.10 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js = 56.10 kB 55.95 kB = 11.49 kB 11.47 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js = 56.10 kB 55.95 kB = 11.49 kB 11.47 kB
oss-stable/react-client/cjs/react-client-flight.development.js = 101.86 kB 101.59 kB = 18.53 kB 18.50 kB
oss-stable-semver/react-client/cjs/react-client-flight.development.js = 101.83 kB 101.57 kB = 18.51 kB 18.47 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js = 100.56 kB 100.30 kB = 18.75 kB 18.70 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js = 100.51 kB 100.25 kB = 18.73 kB 18.68 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js = 100.20 kB 99.94 kB = 18.78 kB 18.73 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browse 8000 r.development.js = 100.15 kB 99.89 kB = 18.75 kB 18.71 kB

Generated by 🚫 dangerJS against 70dcc16

@sebmarkbage
Copy link
Collaborator Author

One thing we could also do is in idle cycles, warm up any remaining lazy references by initializing them. Which could save future CPU work and release memory by figuring out which references will end up being used.

@@ -625,6 +609,7 @@ function initializeModelChunk<T>(chunk: ResolvedModelChunk<T>): void {
initializingHandler = null;

const resolvedModel = chunk.value;
const response = chunk.reason;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I hate it. ... I vote for evil, by the way. 😉

@@ -486,31 +472,31 @@ function createResolvedModelChunk<T>(
value: UninitializedModel,
): ResolvedModelChunk<T> {
// $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
return new ReactPromise(RESOLVED_MODEL, value, null, response);
return new ReactPromise(RESOLVED_MODEL, value, response);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A comment like we have for createInitializedStreamChunk would help avoid confusion:

// We use the reason field to stash the controller since we already have that
// field. It's a bit of a hack but efficient.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's all over every access in this file and indeed every Fiber field too. At some point you just got to add a doc for the whole repo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed React Core Team Opened by a member of the React Core Team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants
0