Skip to content

gpui: Reduce amount of monomorphizations taking place#48014

Merged
osiewicz merged 2 commits intomainfrom
gpui-cleanups
Feb 2, 2026
Merged

gpui: Reduce amount of monomorphizations taking place#48014
osiewicz merged 2 commits intomainfrom
gpui-cleanups

Conversation

@osiewicz
Copy link
Member

@osiewicz osiewicz commented Jan 30, 2026

Re-lands #3266 after recent scheduler changes

Back-of-napkin calculation: editor tests (build) went from 32s to 17s.

Release Notes:

  • N/A

Re-lands #3266 after recent scheduler changes
@cla-bot cla-bot bot added the cla-signed The user has signed the Contributor License Agreement label Jan 30, 2026
@osiewicz osiewicz changed the title gpui: Box futures (again and again and again) gpui: Reduce amount of monomorphizations taking place Jan 30, 2026
@Anthony-Eid
Copy link
Contributor

What does boxed_local do? Just curious why it reduces monomorphizations

@osiewicz
Copy link
Member Author

boxed_local is just a part of the story.
The problem boils down to the fact that we have a function such as follows (it uses FnOnce and not Future, but the concept is really the same):

fn function<R>(a: impl FnOnce() -> R) -> R {
  (a)()
}

impl arguments get desugared by a compiler to:

fn function<R, Fun: FnOnce() -> R>(a: Fun) -> R {
  (a)()
}

Then, the problem (and excessive monomorphizations) come from a fact that each closure you pass into that function is a separate instantiation of function. It also means that a call to a can be inlined within the body of a monomorphized function.
boxed_local turns our impl Future<Output = R> into Box<dyn Future<Output = R>. This is one type per Return type, and not a separate type per closure. It still depends on the return type, but by boxing and erasing a type we're going from O(number of calls to spawn) instantiations to O(number of return types) instantiations - which is likely to be way smaller.
This has downsides.
For one, you need to allocate in order to perform that kind of type erasure. It's not always necessary (if you can use a reference), but in our case we can't, so..
The other downside is that the compiler can no longer inline the call to your closure, because of type erasure.

On the flipside, it does not necessarily have to degrade the performance of your program:

  1. In our case we're making shitton of monomorphizations which (I'm just speculating here) might contribute to trashing of instruction cache. On main each instantiation of spawn is a separate code path.
  2. Inlining really matters when it can unlock additional optimization opportunities for the compiler. Again, I don't think we are operating at a level of granularity with performance where whether something gets inlined or not makes a huge difference to us (esp. with a tradeoff being longer build times).

@Anthony-Eid
Copy link
Contributor

Thanks for such a detailed explanation! I was about to ask about memory allocation but you covered that already.

@osiewicz osiewicz merged commit 45455db into main Feb 2, 2026
29 checks passed
@osiewicz osiewicz deleted the gpui-cleanups branch February 2, 2026 16:18
adb-sh pushed a commit to adb-sh/zed that referenced this pull request Feb 5, 2026
…#48014)

Re-lands zed-industries#3266 after recent scheduler changes

Back-of-napkin calculation: editor tests (build) went from 32s to 17s.

Release Notes:

- N/A
naaiyy added a commit to Glass-HQ/Glass that referenced this pull request Feb 16, 2026
Key changes:
- Reduce monomorphizations in GPUI app.rs (zed-industries#48014)
- Entities no longer implement Element directly, go through AnyElement (zed-industries#48217)
- D3D11 resource upload optimization (zed-industries#48282)
- Migrate features.edit_prediction_provider to edit_predictions.provider (zed-industries#48224)
- Make mercury and sweep non-experimental (zed-industries#48227)
- CompanionView consolidation in block_map (zed-industries#48223)
- Show memory used by language servers (zed-industries#48226)
- Settings links open sub pages (zed-industries#48212)
- Tool security rules that can't be overridden (zed-industries#48209)
- Add sweep_ai privacy mode setting (zed-industries#48220)
- Configurable REPL output size limits (zed-industries#47114)
- Fix .editorconfig files in subdirectories (zed-industries#48203)
- Security updates: bytes v1.11.1, jsonwebtoken v10
- Git UI: hide "View on GitHub" for stashes (zed-industries#48271)
- Indent guide fix in tree view with collapsed folders (zed-industries#48194)
- Edit prediction fixes and improvements

Conflict resolution:
- collab/completion.rs, collab/rpc.rs: deleted (collab removed)
- vim/search.rs: deleted (vim removed)
- livekit_api/Cargo.toml: deleted (livekit removed)
- GPUI files: deleted from Glass (handled in Obsydian-HQ/gpui)
- migrations: combined both ours (m_2026_02_06) and upstream (m_2026_02_02, m_2026_02_03)
- project.rs: kept collab functions removed, restored handle_create_file_for_peer for remote dev
- lsp_store.rs: removed collab-only set_language_server_statuses_from_proto
- proto.rs: kept CreateFileForPeer, removed CreateChannel/CreateChannelResponse
- remote_servers.rs: merged import lists (kept native button imports + added Action)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed The user has signed the Contributor License Agreement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants