gpui: Box `Window` instances (#40733)

Lukas Wirth created

We very frequently move this in and out of the windows slot map on
`update_window_id` calls (and we call this a lot!). This alone showed up
as `memmove`s at roughly 1% perf in Instruments when scrolling a buffer
which makes sense, `Window` itself is 4kb in size. The fix is simple,
just box the `Window` instances, moving a pointer is cheap in
comparison.

Release Notes:

- N/A *or* Added/Fixed/Improved ...

Change summary

crates/gpui/src/app.rs              | 10 +++++-----
crates/gpui/src/app/test_context.rs |  2 +-
crates/gpui/src/window.rs           |  2 +-
3 files changed, 7 insertions(+), 7 deletions(-)

Detailed changes

crates/gpui/src/app.rs 🔗

@@ -553,7 +553,7 @@ pub struct App {
     pub(crate) entities: EntityMap,
     pub(crate) window_update_stack: Vec<WindowId>,
     pub(crate) new_entity_observers: SubscriberSet<TypeId, NewEntityListener>,
-    pub(crate) windows: SlotMap<WindowId, Option<Window>>,
+    pub(crate) windows: SlotMap<WindowId, Option<Box<Window>>>,
     pub(crate) window_handles: FxHashMap<WindowId, AnyWindowHandle>,
     pub(crate) focus_handles: Arc<FocusMap>,
     pub(crate) keymap: Rc<RefCell<Keymap>>,
@@ -964,7 +964,7 @@ impl App {
                     clear.clear();
 
                     cx.window_handles.insert(id, window.handle);
-                    cx.windows.get_mut(id).unwrap().replace(window);
+                    cx.windows.get_mut(id).unwrap().replace(Box::new(window));
                     Ok(handle)
                 }
                 Err(e) => {
@@ -1239,7 +1239,7 @@ impl App {
                     .windows
                     .values()
                     .filter_map(|window| {
-                        let window = window.as_ref()?;
+                        let window = window.as_deref()?;
                         window.invalidator.is_dirty().then_some(window.handle)
                     })
                     .collect::<Vec<_>>()
@@ -1320,7 +1320,7 @@ impl App {
 
     fn apply_refresh_effect(&mut self) {
         for window in self.windows.values_mut() {
-            if let Some(window) = window.as_mut() {
+            if let Some(window) = window.as_deref_mut() {
                 window.refreshing = true;
                 window.invalidator.set_dirty(true);
             }
@@ -2199,7 +2199,7 @@ impl AppContext for App {
             .windows
             .get(window.id)
             .context("window not found")?
-            .as_ref()
+            .as_deref()
             .expect("attempted to read a window that is already on the stack");
 
         let root_view = window.root.clone().unwrap();

crates/gpui/src/window.rs 🔗

@@ -4718,7 +4718,7 @@ impl<V: 'static + Render> WindowHandle<V> {
             .get(self.id)
             .and_then(|window| {
                 window
-                    .as_ref()
+                    .as_deref()
                     .and_then(|window| window.root.clone())
                     .map(|root_view| root_view.downcast::<V>())
             })