Skip to content

script: Add a ServoInternals.garbageCollectAllContexts()#42798

Merged
mrobinson merged 1 commit into
servo:mainfrom
webbeef:servo-internals-force-gc
Feb 28, 2026
Merged

script: Add a ServoInternals.garbageCollectAllContexts()#42798
mrobinson merged 1 commit into
servo:mainfrom
webbeef:servo-internals-force-gc

Conversation

@webbeef

@webbeef webbeef commented Feb 24, 2026

Copy link
Copy Markdown
Contributor

This is useful in about:memory to measure memory usage after running the GC.

The calling page sends a callback to the constellation that in turn wait for all script threads to run the GC and report back.

Testing: Manual testing in about:memory

Before running GC:

Screenshot from 2026-02-23 18-50-46

After running GC:

Screenshot from 2026-02-23 18-51-00

@webbeef webbeef requested a review from gterzian as a code owner February 24, 2026 03:47
@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Feb 24, 2026
@mrobinson

Copy link
Copy Markdown
Member

Could you instead make it so that TestUtils is always exposed to about: memory and then just reuse TestUtils.gc? It's a bit odd that we expose more than one way to garbage collect in the DOM API. For reference, I just removed one of these: #42728.

@webbeef

webbeef commented Feb 24, 2026

Copy link
Copy Markdown
Contributor Author

The TestUtil api is gated by skip-unless CARGO_FEATURE_TESTBINDING and I don't think we should gate about:memory on test bindings being built in.

Also, and correct me if I'm wrong as I only skimmed the code, TestUtils.gc() only seems to GC in the the current script thread, while this patch broadcasts the GC to all script threads.

@mrobinson

Copy link
Copy Markdown
Member

Also, and correct me if I'm wrong as I only skimmed the code, TestUtils.gc() only seems to GC in the the current script thread, while this patch broadcasts the GC to all script threads.

I see. In that case let's rename this to garbageCollectAllContexts to make it clear how it is different from the other garbage collection APIs.

Comment thread components/constellation/constellation.rs Outdated
Comment thread components/constellation/tracing.rs Outdated
Comment thread components/constellation/constellation.rs Outdated
Comment thread components/constellation/constellation.rs Outdated
Comment thread components/script/messaging.rs Outdated
Comment thread components/script/script_thread.rs Outdated
Comment on lines +1977 to +1989
ScriptThreadMessage::ForceGC => {
unsafe {
JS_GC(*GlobalScope::get_cx(), GCReason::API);
}
// Notify the constellation that this script thread's GC is complete.
// Use dummy values for webview_id and pipeline_id since the values
// don't matter in that case.
let _ = self.senders.pipeline_to_constellation_sender.send((
base::id::TEST_WEBVIEW_ID,
base::id::PipelineId::new(),
ScriptToConstellationMessage::ForceGCCompleted,
));
},

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is it possible that the ScriptThread shuts down before the message is received and the Constellation never receives a reply and goes into a state where a GC cannot be forced again?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes - I added a mitigation that by rejecting the promise if we detect that a ScriptThread did shut down during the browser wide GC.

A more proper fix would require to track which script thread did answer and remove dying ones. I'm not sure that the complexity is warranted here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

As this can fail, I think it's better to make this API even simpler. Instead of making this API return a promise, let's just let it happen asynchronously. The user can then just wait for the new memory results to settle. It's not quite as nice, but it's also a bit less of a lie. Opening a new tab or closing one could cause really weird behavior otherwise.

@servo-highfive servo-highfive added S-needs-code-changes Changes have not yet been made that were requested by a reviewer. S-awaiting-review There is new code that needs to be reviewed. and removed S-awaiting-review There is new code that needs to be reviewed. S-needs-code-changes Changes have not yet been made that were requested by a reviewer. labels Feb 24, 2026
@webbeef webbeef force-pushed the servo-internals-force-gc branch from c52a465 to d08840e Compare February 25, 2026 03:09

@mrobinson mrobinson left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good, but let's simplify this a bit.

Comment thread components/shared/script/lib.rs Outdated
Comment thread components/script/script_thread.rs Outdated
Comment on lines +1977 to +1989
ScriptThreadMessage::ForceGC => {
unsafe {
JS_GC(*GlobalScope::get_cx(), GCReason::API);
}
// Notify the constellation that this script thread's GC is complete.
// Use dummy values for webview_id and pipeline_id since the values
// don't matter in that case.
let _ = self.senders.pipeline_to_constellation_sender.send((
base::id::TEST_WEBVIEW_ID,
base::id::PipelineId::new(),
ScriptToConstellationMessage::ForceGCCompleted,
));
},

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

As this can fail, I think it's better to make this API even simpler. Instead of making this API return a promise, let's just let it happen asynchronously. The user can then just wait for the new memory results to settle. It's not quite as nice, but it's also a bit less of a lie. Opening a new tab or closing one could cause really weird behavior otherwise.

@webbeef webbeef force-pushed the servo-internals-force-gc branch 3 times, most recently from 1670183 to ad9de9a Compare February 26, 2026 05:40
Comment thread components/shared/constellation/from_script_message.rs Outdated
@servo-highfive servo-highfive removed the S-awaiting-review There is new code that needs to be reviewed. label Feb 26, 2026
@mrobinson mrobinson changed the title memory: Add a servo.forceGC() api script: Add a ServoIternals.garbageCollectAllContexts() Feb 26, 2026
@mrobinson mrobinson changed the title script: Add a ServoIternals.garbageCollectAllContexts() script: Add a ServoInternals.garbageCollectAllContexts() Feb 26, 2026
This is useful in about:memory to measure memory usage after
running the GC.

The calling page sends a callback to the constellation that
in turn wait for all script threads to run the GC and report
back.

Signed-off-by: webbeef <me@webbeef.org>
@webbeef webbeef force-pushed the servo-internals-force-gc branch from ad9de9a to 2f42e28 Compare February 26, 2026 07:36
@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Feb 26, 2026
@webbeef

webbeef commented Feb 28, 2026

Copy link
Copy Markdown
Contributor Author

@mrobinson can you send that to the merge queue?

@jdm jdm added this pull request to the merge queue Feb 28, 2026
@servo-highfive servo-highfive added the S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. label Feb 28, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Feb 28, 2026
@servo-highfive servo-highfive added S-tests-failed The changes caused existing tests to fail. and removed S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. labels Feb 28, 2026
@mrobinson mrobinson added this pull request to the merge queue Feb 28, 2026
@servo-highfive servo-highfive removed the S-tests-failed The changes caused existing tests to fail. label Feb 28, 2026
@servo-highfive servo-highfive added the S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. label Feb 28, 2026
Merged via the queue into servo:main with commit 1ad41dc Feb 28, 2026
39 checks passed
@servo-highfive servo-highfive removed the S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. label Feb 28, 2026
simonwuelker pushed a commit to simonwuelker/servo that referenced this pull request Mar 3, 2026
This is useful in about:memory to measure memory usage after running the
GC.

The calling page sends a callback to the constellation that in turn wait
for all script threads to run the GC and report back.

Testing: Manual testing in `about:memory`

Before running GC:

<img width="2048" height="1480" alt="Screenshot from 2026-02-23
18-50-46"
src="https://github.com/user-attachments/assets/fd8399c1-fbc7-4f4c-886d-f29629ef8369"
/>

After running GC:

<img width="2048" height="1480" alt="Screenshot from 2026-02-23
18-51-00"
src="https://github.com/user-attachments/assets/82c793f7-8229-4de4-9cb5-47c94383b410"
/>

Signed-off-by: webbeef <me@webbeef.org>
offline-ant pushed a commit to offline-ant/havi that referenced this pull request Jun 4, 2026
This is useful in about:memory to measure memory usage after running the
GC.

The calling page sends a callback to the constellation that in turn wait
for all script threads to run the GC and report back.

Testing: Manual testing in `about:memory`

Before running GC:

<img width="2048" height="1480" alt="Screenshot from 2026-02-23
18-50-46"
src="https://github.com/user-attachments/assets/fd8399c1-fbc7-4f4c-886d-f29629ef8369"
/>

After running GC:

<img width="2048" height="1480" alt="Screenshot from 2026-02-23
18-51-00"
src="https://github.com/user-attachments/assets/82c793f7-8229-4de4-9cb5-47c94383b410"
/>

Signed-off-by: webbeef <me@webbeef.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-awaiting-review There is new code that needs to be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants