browser: Virtualize sidebar tab list and pre-collect tab render data#57
Open
Yabuku-xD wants to merge 2 commits into
Open
browser: Virtualize sidebar tab list and pre-collect tab render data#57Yabuku-xD wants to merge 2 commits into
Yabuku-xD wants to merge 2 commits into
Conversation
bcbbd7b to
f051be1
Compare
Four targeted improvements to the browser crate's rendering pipeline: 1. Gate FrameReady on suspension state (tab.rs): Skip emitting TabEvent::FrameReady for suspended tabs. CEF already stops rendering hidden browsers, but this prevents any in-flight frames from propagating cx.notify() after suspension. 2. Gate FrameReady cx.notify() on surface visibility (browser_view.rs): Only trigger a re-render when BrowserSurfaceState is Visible. In-flight FrameReady events queued just before a mode switch no longer cause spurious layout work on the hidden browser view. 3. Split RenderState Mutex (render_handler.rs, tab.rs, client.rs, life_span_handler.rs): Extract current_frame into its own Arc<Mutex<Option<CVPixelBuffer>>> separate from the geometry fields (width, height, scale_factor). CEF's view_rect and screen_info callbacks no longer share a lock with the 60fps frame write path, eliminating cross-contention between geometry queries and frame writes. 4. Compute pinned_count once per render pass (tab_strip.rs, browser_view.rs): Both render_tab_strip and render_sidebar previously ran an independent O(n) tab scan to count pinned tabs. The count is now computed once in the render() method via a pinned_tab_count() helper and passed as a parameter to both render methods.
Two improvements to the non-macOS tab rendering path: Sidebar virtualization (render_sidebar): - Replace the O(n) unpinned tab list with gpui::uniform_list, which renders only the rows visible in the viewport. With 50 tabs and ~10 visible, element construction drops from O(50) to O(10-15) per paint frame. A UniformListScrollHandle field is added to BrowserView to track scroll state across renders. - Split the sidebar into a fixed pinned-tab grid (always visible, never scrolled) and a virtualized unpinned list. Pinned tab data is pre-collected once via collect_tab_row_data() before the element tree is built. - Extract the per-row rendering logic into render_sidebar_tab_rows(), the uniform_list processor called lazily for visible rows only. Tab strip data pre-collection (render_tab_strip): - Add TabRowData struct and collect_tab_row_data() helper to snapshot all tab state in a single pass (one entity read per tab). Both the pinned dock and unpinned strip iterate the pre-collected Vec instead of re-reading entity state mid-render.
f051be1 to
66efada
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two improvements to the non-macOS tab rendering path. (macOS uses the native
ModeNavigationHostpath and is unaffected.)Sidebar virtualization (
render_sidebar,BrowserView):overflow_y_scrollcontainer (which built element trees for all tabs on every paint) withgpui::uniform_list, which renders only the rows visible in the viewport. With 50 tabs and ~10 visible at a time, element construction drops from O(n) → O(visible) per paint frame.UniformListScrollHandletoBrowserViewto preserve scroll position across renders.collect_tab_row_data()before the element tree is built.render_sidebar_tab_rows()— theuniform_listprocessor called lazily for visible rows only.Tab strip data pre-collection (
render_tab_strip):TabRowDatastruct andcollect_tab_row_data()helper to snapshot all tab state in a single pass (one entity map read per tab). Both the pinned dock and unpinned strip now iterate a pre-collectedVecinstead of callingtab.read(cx)mid-render.Test plan
cargo check -p browserpasses with no errorsRelease Notes: