Skip to content

fix: reduce overview open lag#130

Merged
flexagoon merged 4 commits intoflexagoon:mainfrom
elkhaligy:perf/optimize-overview-lag
Mar 27, 2026
Merged

fix: reduce overview open lag#130
flexagoon merged 4 commits intoflexagoon:mainfrom
elkhaligy:perf/optimize-overview-lag

Conversation

@elkhaligy
Copy link
Copy Markdown

@elkhaligy elkhaligy commented Mar 15, 2026

Summary

  • Cache Gio.Settings object and fractional scaling result in
    windowScaleFactor() — was allocating a new GSettings object on
    every call, which runs per-frame × per-window inside
    vfunc_allocate during overview animations (60fps × N windows)
  • Replace new Error().stack call stack inspection in
    addShadowInOverview with window.get_transient_for() to detect
    attached dialogs — stack trace capture fired for every window on
    every overview open
  • Deduplicate getPref('global-rounded-corner-settings') calls in
    updateShadowActorStyle from 3-4x down to 1x per call
  • Skip queue_redraw() when the shadow style string hasn't changed,
    avoiding unnecessary GPU repaints on focus changes
  • Prune disconnected entries from connections[] array on window
    close, preventing unbounded growth over the session

Root cause

The main bottleneck was windowScaleFactor() calling
Gio.Settings.new('org.gnome.mutter') on every invocation. This
function is called from vfunc_allocate on the overview shadow
clone actors, which Clutter calls on every layout pass during
overview animations, meaning every frame × every window was
allocating a new GSettings object and reading from the GSettings
daemon. The fix caches the settings object and the derived boolean
at module level, invalidating only when experimental-features
actually changes.

Closes #22

- Cache Gio.Settings object and fractional scaling result in
  windowScaleFactor() — was allocating a new GSettings object on every
  call, which runs per-frame per-window inside vfunc_allocate during
  overview animations
- Replace new Error().stack call stack inspection in addShadowInOverview
  with window.get_transient_for() check to detect attached dialogs
- Deduplicate getPref('global-rounded-corner-settings') calls in
  updateShadowActorStyle from 3-4x down to 1x per call
- Skip queue_redraw() when shadow style string hasn't changed
- Prune disconnected entries from connections[] array on window close
Copy link
Copy Markdown
Owner

@flexagoon flexagoon left a comment

Choose a reason for hiding this comment

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

A few nits, LGTM otherwise, thanks!

Comment on lines +115 to +116
let i = connections.length;
while (i--) {
Copy link
Copy Markdown
Owner

@flexagoon flexagoon Mar 18, 2026

Choose a reason for hiding this comment

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

Could this use connections.entries() instead?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Using connections.entries() will make this method two pass as we will need to disconnect and then collect the indices of the disconnected objects, after that we will splice the connections array, so I think this one pass solution is better.

Copy link
Copy Markdown
Owner

@flexagoon flexagoon Mar 19, 2026

Choose a reason for hiding this comment

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

@elkhaligy I see, then could you please add a code comment explaining that? (And preferably also the reason for why the array is spliced in the first place)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done, added comments

@elkhaligy
Copy link
Copy Markdown
Author

Great! I will work on the comments

Shehab Elkhaligy added 2 commits March 19, 2026 16:47
getMutterSettings was only ever called in one place, so inline it
directly into isFractionalScalingEnabled where the lazy init and signal
subscription make more contextual sense. Also move misplaced imports to
the top of the file and add JSDoc to isFractionalScalingEnabled and
clearMutterSettingsCache.
Without removing the entry after disconnecting, the array would hold
references to dead window GObjects indefinitely, leaking memory
proportional to the number of windows opened over the session.
@flexagoon flexagoon self-requested a review March 21, 2026 01:11
@flexagoon flexagoon changed the title perf: reduce overview open lag fix: reduce overview open lag Mar 27, 2026
@flexagoon flexagoon merged commit cc09d26 into flexagoon:main Mar 27, 2026
@flexagoon
Copy link
Copy Markdown
Owner

@elkhaligy thank you so much!

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.

Massive lag when calling up the window overview

2 participants