Skip to content

Conversation

@eps1lon
Copy link
Collaborator

@eps1lon eps1lon commented Oct 15, 2025

Turns out Error.stackTraceLimit does affect Error() performance (in v8). But only if you're not inspecting with a debugger (e.g. ChromeDevTools is closed). Where this matters more is for SSR where you commonly aren't actively inspecting. Safari (JSC) and Firefox (SpiderMonkey) seem to have no issue with a high stack trace limit. JSC even defaults to 100 while Firefox doesn't even have Error.stackTraceLimit.

A higher limit is nice though for showing sync stacks. Especially with ignore-listing, a high limit can still produce nice stacks when most of the frames end up in 3rd party code. For Owner Stacks, we usually don't need very deep stacks. You mostly just have a .map or useMemo that creates the JSX.

So now we're setting the limit to 10 (v8 default) which allows frameworks to use a higher limit for nice sync stacks without severely degrading performance due to React Owner Stacks. 5 didn't show a meaningful difference in apps exhausting the Owner Stack limit of 10k in SSR.

The ownerstack fixture won't show the improvement since that already uses the default stack trace limit.

One thing to keep an eye out is Hermes where I haven't tested it. Only v8, JSC and SpiderMonkey.

@meta-cla meta-cla bot added the CLA Signed label Oct 15, 2025
@github-actions github-actions bot added the React Core Team Opened by a member of the React Core Team label Oct 15, 2025
Comment on lines 380 to 397
let debugStackDEV = false;
if (__DEV__) {
if (trackActualOwner) {
if (supportsSettingStackTraceLimit) {
try {
const previousStackTraceLimit = Error.stackTraceLimit;
Error.stackTraceLimit = ownerStackTraceLimit;
debugStackDEV = Error('react-stack-top-frame');
Error.stackTraceLimit = previousStackTraceLimit;
} catch {}
}
if (!debugStackDEV) {
debugStackDEV = Error('react-stack-top-frame');
}
} else {
debugStackDEV = unknownOwnerDebugStack;
}
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Same approach everywhere but I didn't create a helper to save a stackframe. gcc doesn't have a @inline directive afaict. Only @noinline

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yea, and I'm actually concerned about the getOwner call which is too large to get inlined. We're missing a lot of inlining here.

@react-sizebot
Copy link

react-sizebot commented Oct 15, 2025

Comparing: 903366b...d07263e

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 = 605.41 kB 605.41 kB = 107.22 kB 107.21 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 = 664.38 kB 664.38 kB = 117.09 kB 117.09 kB
facebook-www/ReactDOM-prod.classic.js = 688.25 kB 688.25 kB = 121.13 kB 121.13 kB
facebook-www/ReactDOM-prod.modern.js = 678.67 kB 678.67 kB = 119.48 kB 119.48 kB
oss-experimental/react/cjs/react-jsx-runtime.react-server.development.js +4.85% 13.36 kB 14.01 kB +1.67% 3.53 kB 3.59 kB
oss-stable-semver/react/cjs/react-jsx-runtime.react-server.development.js +4.85% 13.36 kB 14.01 kB +1.67% 3.53 kB 3.59 kB
oss-stable/react/cjs/react-jsx-runtime.react-server.development.js +4.85% 13.36 kB 14.01 kB +1.67% 3.53 kB 3.59 kB
oss-experimental/react/cjs/react-jsx-dev-runtime.react-server.development.js +4.85% 13.36 kB 14.01 kB +1.70% 3.53 kB 3.59 kB
oss-stable-semver/react/cjs/react-jsx-dev-runtime.react-server.development.js +4.85% 13.36 kB 14.01 kB +1.70% 3.53 kB 3.59 kB
oss-stable/react/cjs/react-jsx-dev-runtime.react-server.development.js +4.85% 13.36 kB 14.01 kB +1.70% 3.53 kB 3.59 kB
oss-experimental/react/cjs/react-jsx-runtime.development.js +3.43% 12.60 kB 13.03 kB +1.68% 3.40 kB 3.46 kB
oss-stable-semver/react/cjs/react-jsx-runtime.development.js +3.43% 12.60 kB 13.03 kB +1.68% 3.40 kB 3.46 kB
oss-stable/react/cjs/react-jsx-runtime.development.js +3.43% 12.60 kB 13.03 kB +1.68% 3.40 kB 3.46 kB
facebook-react-native/react/cjs/JSXRuntime-dev.js +3.41% 12.68 kB 13.11 kB +1.79% 3.40 kB 3.46 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/cjs/react-jsx-runtime.react-server.development.js +4.85% 13.36 kB 14.01 kB +1.67% 3.53 kB 3.59 kB
oss-stable-semver/react/cjs/react-jsx-runtime.react-server.development.js +4.85% 13.36 kB 14.01 kB +1.67% 3.53 kB 3.59 kB
oss-stable/react/cjs/react-jsx-runtime.react-server.development.js +4.85% 13.36 kB 14.01 kB +1.67% 3.53 kB 3.59 kB
oss-experimental/react/cjs/react-jsx-dev-runtime.react-server.development.js +4.85% 13.36 kB 14.01 kB +1.70% 3.53 kB 3.59 kB
oss-stable-semver/react/cjs/react-jsx-dev-runtime.react-server.development.js +4.85% 13.36 kB 14.01 kB +1.70% 3.53 kB 3.59 kB
oss-stable/react/cjs/react-jsx-dev-runtime.react-server.development.js +4.85% 13.36 kB 14.01 kB +1.70% 3.53 kB 3.59 kB
oss-experimental/react/cjs/react-jsx-runtime.development.js +3.43% 12.60 kB 13.03 kB +1.68% 3.40 kB 3.46 kB
oss-stable-semver/react/cjs/react-jsx-runtime.development.js +3.43% 12.60 kB 13.03 kB +1.68% 3.40 kB 3.46 kB
oss-stable/react/cjs/react-jsx-runtime.development.js +3.43% 12.60 kB 13.03 kB +1.68% 3.40 kB 3.46 kB
facebook-react-native/react/cjs/JSXRuntime-dev.js +3.41% 12.68 kB 13.11 kB +1.79% 3.40 kB 3.46 kB
oss-experimental/react/cjs/react-jsx-dev-runtime.development.js +1.77% 12.20 kB 12.42 kB +1.47% 3.39 kB 3.44 kB
oss-stable-semver/react/cjs/react-jsx-dev-runtime.development.js +1.77% 12.20 kB 12.42 kB +1.47% 3.39 kB 3.44 kB
oss-stable/react/cjs/react-jsx-dev-runtime.development.js +1.77% 12.20 kB 12.42 kB +1.47% 3.39 kB 3.44 kB
facebook-react-native/react/cjs/JSXDEVRuntime-dev.js +1.76% 12.28 kB 12.49 kB +1.47% 3.40 kB 3.45 kB
facebook-www/JSXDEVRuntime-dev.classic.js +1.69% 12.78 kB 12.99 kB +1.45% 3.51 kB 3.56 kB
facebook-www/JSXDEVRuntime-dev.modern.js +1.69% 12.78 kB 12.99 kB +1.45% 3.51 kB 3.56 kB
facebook-react-native/react/cjs/React-dev.js +1.66% 52.05 kB 52.91 kB +0.86% 11.57 kB 11.67 kB
facebook-www/React-dev.modern.js +1.59% 54.30 kB 55.17 kB +0.78% 12.09 kB 12.18 kB
facebook-www/React-dev.classic.js +1.59% 54.30 kB 55.17 kB +0.78% 12.09 kB 12.19 kB
oss-stable-semver/react/cjs/react.react-server.development.js +0.70% 30.69 kB 30.90 kB +0.66% 7.31 kB 7.36 kB
oss-stable/react/cjs/react.react-server.development.js +0.70% 30.71 kB 30.93 kB +0.61% 7.34 kB 7.38 kB
oss-experimental/react/cjs/react.react-server.development.js +0.56% 38.29 kB 38.50 kB +0.51% 8.99 kB 9.04 kB
oss-stable-semver/react/cjs/react.development.js +0.45% 48.24 kB 48.46 kB +0.42% 10.95 kB 10.99 kB
oss-stable/react/cjs/react.development.js +0.45% 48.27 kB 48.48 kB +0.40% 10.97 kB 11.02 kB
oss-experimental/react/cjs/react.development.js +0.43% 50.41 kB 50.63 kB +0.43% 11.35 kB 11.40 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js = 187.98 kB 187.43 kB = 32.92 kB 32.82 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js = 187.98 kB 187.43 kB = 32.92 kB 32.82 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js = 187.96 kB 187.41 kB = 32.91 kB 32.81 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js = 187.96 kB 187.41 kB = 32.91 kB 32.81 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js = 188.85 kB 188.30 kB = 33.07 kB 32.95 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js = 188.83 kB 188.28 kB = 33.05 kB 32.94 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.development.js = 186.55 kB 186.00 kB = 32.65 kB 32.55 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.development.js = 186.55 kB 186.00 kB = 32.65 kB 32.55 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.development.js = 187.42 kB 186.87 kB = 32.79 kB 32.68 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js = 184.85 kB 184.30 kB = 32.38 kB 32.28 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js = 184.85 kB 184.30 kB = 32.38 kB 32.28 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js = 185.72 kB 185.16 kB = 32.52 kB 32.41 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js = 183.32 kB 182.77 kB = 32.37 kB 32.27 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js = 183.27 kB 182.72 kB = 32.35 kB 32.25 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js = 183.17 kB 182.62 kB = 32.32 kB 32.21 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js = 183.17 kB 182.62 kB = 32.32 kB 32.21 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js = 182.70 kB 182.15 kB = 32.20 kB 32.10 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js = 182.65 kB 182.10 kB = 32.18 kB 32.08 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js = 184.21 kB 183.65 kB = 32.51 kB 32.40 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js = 184.04 kB 183.49 kB = 32.46 kB 32.35 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js = 183.59 kB 183.03 kB = 32.35 kB 32.23 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js = 180.12 kB 179.57 kB = 31.72 kB 31.61 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js = 180.07 kB 179.52 kB = 31.69 kB 31.58 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js = 181.01 kB 180.45 kB = 31.86 kB 31.74 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js = 178.16 kB 177.61 kB = 31.27 kB 31.17 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js = 178.11 kB 177.56 kB = 31.25 kB 31.15 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js = 179.05 kB 178.49 kB = 31.41 kB 31.30 kB
oss-stable/react-client/cjs/react-client-flight.development.js = 173.54 kB 172.99 kB = 30.21 kB 30.10 kB
oss-stable-semver/react-client/cjs/react-client-flight.development.js = 173.52 kB 172.97 kB = 30.19 kB 30.08 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js = 181.96 kB 181.38 kB = 32.18 kB 32.07 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js = 181.96 kB 181.38 kB = 32.18 kB 32.07 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js = 181.94 kB 181.36 kB = 32.17 kB 32.06 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js = 181.94 kB 181.36 kB = 32.17 kB 32.06 kB
oss-experimental/react-client/cjs/react-client-flight.development.js = 174.42 kB 173.87 kB = 30.37 kB 30.25 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js = 182.87 kB 182.29 kB = 32.32 kB 32.21 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js = 182.85 kB 182.26 kB = 32.31 kB 32.19 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js = 178.73 kB 178.15 kB = 31.67 kB 31.56 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js = 178.73 kB 178.15 kB = 31.67 kB 31.56 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js = 179.64 kB 179.05 kB = 31.81 kB 31.70 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js = 224.35 kB 223.49 kB = 49.61 kB 49.42 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js = 224.32 kB 223.46 kB = 49.58 kB 49.39 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js = 225.50 kB 224.62 kB = 49.83 kB 49.61 kB

Generated by 🚫 dangerJS against d07263e

@eps1lon eps1lon requested a review from sebmarkbage October 15, 2025 19:39
@eps1lon eps1lon marked this pull request as ready for review October 15, 2025 19:39
@hoxyq
Copy link
Contributor

hoxyq commented Oct 15, 2025

Hermes doesn't implement this field, so it should be safe. We didn't observe any performance issues with Error object construction.

Copy link
Collaborator

@sebmarkbage sebmarkbage left a comment

Choose a reason for hiding this comment

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

Too much. I'm concerned about just these lines being too much:

const previousStackTraceLimit = Error.stackTraceLimit;
Error.stackTraceLimit = ownerStackTraceLimit;
debugStackDEV = Error('react-stack-top-frame');
Error.stackTraceLimit = previousStackTraceLimit

We shouldn't add a single line of code more to the actual runtime.

Comment on lines 380 to 397
let debugStackDEV = false;
if (__DEV__) {
if (trackActualOwner) {
if (supportsSettingStackTraceLimit) {
try {
const previousStackTraceLimit = Error.stackTraceLimit;
Error.stackTraceLimit = ownerStackTraceLimit;
debugStackDEV = Error('react-stack-top-frame');
Error.stackTraceLimit = previousStackTraceLimit;
} catch {}
}
if (!debugStackDEV) {
debugStackDEV = Error('react-stack-top-frame');
}
} else {
debugStackDEV = unknownOwnerDebugStack;
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Yea, and I'm actually concerned about the getOwner call which is too large to get inlined. We're missing a lot of inlining here.

Error.stackTraceLimit = ownerStackTraceLimit;
debugStackDEV = Error('react-stack-top-frame');
Error.stackTraceLimit = previousStackTraceLimit;
} catch {}
Copy link
Collaborator

Choose a reason for hiding this comment

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

try/catch is notorious for deopting. It's better in modern browsers but can still trigger extra stuff on the stack and avoid inlining capabilities by making larger code.

We need to cut everything. We should just let it throw if this is not supported.

let debugStackDEV = false;
if (__DEV__) {
if (trackActualOwner) {
if (supportsSettingStackTraceLimit) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm concerned about this unnecessary condition adding to code size (in terms of memory / JIT optimization and not download size) and the extra lookup every call.

We should make two entire copies of the function and switch which function we use instead so that the function that we use doesn't have to make any additional checks at runtime.

Alternatively we should just assume that you can set it and not support environments that don't play ball.

@eps1lon eps1lon requested a review from sebmarkbage October 16, 2025 07:54
@eps1lon eps1lon merged commit d8aa94b into facebook:main Oct 16, 2025
240 of 241 checks passed
@eps1lon eps1lon deleted the sebbie/10-15-only_capture_debug_stacks_for_up_to_10_frames branch October 16, 2025 16:00
github-actions bot pushed a commit that referenced this pull request Oct 16, 2025
github-actions bot pushed a commit that referenced this pull request Oct 16, 2025
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