Skip to content

Don't leak WorkspaceThumbnail objects #291

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 on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 5, 2024

Conversation

pobrn
Copy link
Contributor

@pobrn pobrn commented Nov 4, 2024

From the main commit:

WorkspaceThumbnail objects must be explicitly destroy()ed, otherwise
they will not be garbage collected. Furthermore, each such object
subscribes to the "window-{left,entered}-monitor" signal of the
particular MetaDisplay. Thus leaking these thumbnails causes those
signals to have a very large number of subscribers after the popup
has been shown a sufficient number of times. This shows up in profiling,
and also causes stuttering when a window is moved between monitors or created.

For example, with 4*4=16 workspaces on 3 monitors, every time the popup
is shown 48 new subscribers are added to both signals. After a couple
days of uptime, there may be thousands.

Fix that by destroying the WorkspaceThumbnail objects in `_onDestroy()`.

Do not store the list of thumbnails and workspace names as they
are not needed after construction.
@pobrn pobrn mentioned this pull request Nov 4, 2024
@pobrn pobrn force-pushed the dont_leak_WorkspaceThumbnails branch from 18831f0 to 358696a Compare November 4, 2024 23:06
WorkspaceThumbnail objects must be explicitly destroy()ed, otherwise
they will not be garbage collected. Furthermore, each such object
subscribes to the "window-{left,entered}-monitor" signal of the
particular MetaDisplay. Thus leaking these thumbnails causes those
signals to have a very large number of subscribers after the popup
has been shown a sufficient number of times. This shows up in profiling,
and also causes stuttering when a window is moved between monitors or created.

For example, with 4*4=16 workspaces on 3 monitors, every time the popup
is shown 48 new subscribers are added to both signals. After a couple
days of uptime, there may be thousands.

Fix that by destroying the WorkspaceThumbnail objects in `_onDestroy()`.
@pobrn pobrn force-pushed the dont_leak_WorkspaceThumbnails branch from 358696a to 92d1e6c Compare November 4, 2024 23:17
Copy link
Owner

@mzur mzur left a comment

Choose a reason for hiding this comment

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

Looks good, thanks a lot! How did you do the profiling?

@mzur mzur merged commit 0d01301 into mzur:master Nov 5, 2024
@pobrn pobrn deleted the dont_leak_WorkspaceThumbnails branch November 5, 2024 11:38
@pobrn
Copy link
Contributor Author

pobrn commented Nov 5, 2024

I used sysprof, and that showed one promising candidate for the offending call stack.

Flame graph from sysprof

In one particular recording about 13.5% of the sampled call stacks were contained the g_signal_emit_by_name() call inside meta_window_update_monitor(). And since moving windows between monitors is where I experienced stuttering, I thought it should be something there.

Another sign was that gnome-shell was actually running, it was scheduled on a CPU:

Profiler marks and CPU

You can see that Meta::Later::invoke() takes too long, ~175 ms above. That is the part under on_before_update.lto_priv.0 in a particular invocation of the call stack from earlier.

From the call stack, I was quite certain that the issue must be with the window-{left,entered}-monitor signals. I am not exactly sure how, but I did realize somehow that showing the workspace switcher popup many times will cause the stuttering when moving windows between monitors. So I first tested with this extension disabled, I could not reproduce the issue.

I also modified gnome-shell to print log messages in {Workspace,WorkspaceThumbnail}::_windowEnteredMonitor(). And from that it seemed that WorkspaceThumbnail objects were leaked or similar. Then I narrowed it down to the part that shows the workspace popup as when show-popup == false, the issue disappeared.

Then I started using FinalizationRegistry to check what is getting leaked, and it became clear that the objects in WorkspaceSwitcherPopup::_items (the WorkspaceThumbnails) do not get finalized. Looking at gnome-shell revealed that they individually .destroy() every WorkspaceThumbnail after they are done using them. So I did the same here, and it appears to have solved the issue.

@mzur
Copy link
Owner

mzur commented Nov 5, 2024

Thanks a lot for the writeup! This will help debugging similar issues in the future.

@mzur mzur mentioned this pull request Mar 18, 2025
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