Skip to content

Conversation

andreiborza
Copy link
Member

@andreiborza andreiborza commented Sep 19, 2025

We often store scopes on spans via setCapturedScopesOnSpan and retrieve them via getCapturedScopesOnSpan. This change wraps the scopes in WeakRef to attempt fixing a potential memory leak when spans hold on to scopes indefinitely.

The downside is spans might end up with undefined scopes on them if the scope was garbage collected, we'll have to see if that's an issue or not.

Copy link
Contributor

github-actions bot commented Sep 19, 2025

size-limit report 📦

Path Size % Change Change
@sentry/browser 24.26 kB +0.13% +31 B 🔺
@sentry/browser - with treeshaking flags 22.77 kB +0.14% +31 B 🔺
@sentry/browser (incl. Tracing) 40.4 kB +0.17% +66 B 🔺
@sentry/browser (incl. Tracing, Replay) 78.78 kB +0.07% +53 B 🔺
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 68.44 kB +0.1% +62 B 🔺
@sentry/browser (incl. Tracing, Replay with Canvas) 83.44 kB +0.06% +50 B 🔺
@sentry/browser (incl. Tracing, Replay, Feedback) 95.66 kB +0.07% +66 B 🔺
@sentry/browser (incl. Feedback) 40.97 kB +0.06% +24 B 🔺
@sentry/browser (incl. sendFeedback) 28.91 kB +0.12% +34 B 🔺
@sentry/browser (incl. FeedbackAsync) 33.84 kB +0.14% +45 B 🔺
@sentry/react 25.98 kB +0.15% +37 B 🔺
@sentry/react (incl. Tracing) 42.38 kB +0.16% +64 B 🔺
@sentry/vue 28.78 kB +0.22% +63 B 🔺
@sentry/vue (incl. Tracing) 42.21 kB +0.16% +65 B 🔺
@sentry/svelte 24.29 kB +0.19% +45 B 🔺
CDN Bundle 25.77 kB +0.11% +28 B 🔺
CDN Bundle (incl. Tracing) 40.24 kB +0.21% +83 B 🔺
CDN Bundle (incl. Tracing, Replay) 76.46 kB +0.1% +74 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) 81.96 kB +0.09% +73 B 🔺
CDN Bundle - uncompressed 75.37 kB +0.19% +142 B 🔺
CDN Bundle (incl. Tracing) - uncompressed 119.13 kB +0.21% +239 B 🔺
CDN Bundle (incl. Tracing, Replay) - uncompressed 234.25 kB +0.11% +239 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 247.02 kB +0.1% +239 B 🔺
@sentry/nextjs (client) 44.4 kB +0.14% +62 B 🔺
@sentry/sveltekit (client) 40.82 kB +0.15% +61 B 🔺
@sentry/node-core 50.02 kB +0.09% +41 B 🔺
@sentry/node 152.25 kB +0.05% +63 B 🔺
@sentry/node - without tracing 91.94 kB +0.07% +59 B 🔺
@sentry/aws-serverless 105.39 kB +0.06% +62 B 🔺

View base workflow run

Copy link
Contributor

github-actions bot commented Sep 19, 2025

node-overhead report 🧳

Note: This is a synthetic benchmark with a minimal express app and does not necessarily reflect the real-world performance impact in an application.

Scenario Requests/s % of Baseline Prev. Requests/s Change %
GET Baseline 8,721 - 8,789 -1%
GET With Sentry 1,271 15% 1,360 -7%
GET With Sentry (error only) 5,861 67% 5,924 -1%
POST Baseline 1,163 - 1,201 -3%
POST With Sentry 486 42% 516 -6%
POST With Sentry (error only) 1,035 89% 1,035 -
MYSQL Baseline 3,256 - 3,265 -0%
MYSQL With Sentry 402 12% 433 -7%
MYSQL With Sentry (error only) 2,618 80% 2,673 -2%

View base workflow run

Copy link
Member

@Lms24 Lms24 left a comment

Choose a reason for hiding this comment

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

Interesting catch! Yeah, let's give this a try!

I wonder though how this lead to a memory leak. Sure, a span holds references to scopes but shouldn't the span be GC'd at some point, leading to the scopes also being GC'd? Or is there anything else holding a reference to any of the two that doesn't get GC'd?

@andreiborza
Copy link
Member Author

I wonder though how this lead to a memory leak. Sure, a span holds references to scopes but shouldn't the span be GC'd at some point, leading to the scopes also being GC'd? Or is there anything else holding a reference to any of the two that doesn't get GC'd?

This is just a shot in the dark basically. I investigated a heap snapshot and saw that we retained a lot of memory from isolationscopes so @mydea and I figured this might be worth a try. Could be the case if spans, for some reasons, are not ending.

cursor[bot]

This comment was marked as outdated.

cursor[bot]

This comment was marked as outdated.

cursor[bot]

This comment was marked as outdated.

cursor[bot]

This comment was marked as outdated.

We often store scopes on spans via `setCapturedScopesOnSpan` and retrieve them
via `getCapturedScopesOnSpan`. This change wraps the scopes in `WeakRef` to
attempt fixing a potential memory leak when spans hold on to scopes
indefinitely.

The downside is scopes might end up with undefined scopes on them if the scope
was garbage collected, we'll have to see if that's an issue or not.
@andreiborza andreiborza requested a review from Lms24 September 22, 2025 14:06
@andreiborza andreiborza merged commit b685be6 into develop Sep 22, 2025
367 of 369 checks passed
@andreiborza andreiborza deleted the ab/weakref-scopes branch September 22, 2025 14:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants