zed/crates
Piotr Osiewicz d338e4a8a6
editor: Improve performance of edit coalescing (#14567)
# Background
In https://github.com/zed-industries/zed/issues/14408 we received a
repro for "Replace all" being slow, even after the work I did
https://github.com/zed-industries/zed/pull/13654. Admittedly #13654 was
a pretty straightforward change.
Under the profiler it turned out that we're spending *10 seconds* in
`memmove` on main thread. Ugh. Not great. The direct ancestor of the
memmove call was
66f0c390a8/crates/editor/src/display_map/tab_map.rs (L108-L119)

What?

# Accidental O(n^2)
We have a bunch of `consolidate_*_edits` functions which take a list of
Fold/Tab/Inlay/Wrap edits and merge consecutive edits if their ranges
overlap/are next to one another. The loop usually goes as follows:
```
while ix < edits.len() {
    let (prev_edits, next_edits) = edits.split_at_mut(ix);
    let prev_edit = prev_edits.last_mut().unwrap();
    let edit = &next_edits[0];
    if PREV_EDIT_CAN_BE_MERGED_WITH_CURRENT_ONE {
        MERGE_EDITS(prev_edit, edit);
        edits.remove(ix); // !!
    } else {
        ix += 1;
    }
}
```
The problem is the call to `.remove` - it has to shift all of the
consecutive elements in the `edits` vector! Thus, when processing the
edits from the original repro (where consolidation shrinks the edit list
from 210k entries to 30k), we mostly spend time moving entries in memory
around.

Thus, the original repro isn't really an issue with replace_all; it's
just that replace_all is one of the few tools available to the end user
that can apply large # of edits in a single transaction.

# Solution
In this PR I address the issue by rewriting the loop in a way that does
not throw items away via `.remove`. Instead, `Iterator::scan` is used,
which lets us achieve the same logic without having the pitfalls of
`.remove`s.
Crucially, **this code does not allocate a new backing buffer for
edits** (see [this article for
rationale](https://blog.polybdenum.com/2024/01/17/identifying-the-collect-vec-memory-leak-footgun.html));
with `vec.into_iter().scan().filter_map().collect()` we still use the
same underlying buffer as the one that's passed into `consolidate_*`
functions. In development I verified that by checking whether the
pointers to backing storage of a Vec are the same before and after the
consolidation.

# Results

### Before
Nightly 0.145.0
[66f0c390a8](66f0c390a8)


https://github.com/user-attachments/assets/8b0ad3bc-86d6-4f8a-850c-ebb86e8b3bfc

(~13s end-to-end)
### After


https://github.com/user-attachments/assets/366835db-1d84-4f95-8c74-b1506a9fabec

(~2s end-to-end)

The remaining lag is (I think) lies in `TextSummary` calculation and not
the consolidation itself. Thus, for the purposes of scoping this PR,
I'll tackle it separately.

Release Notes:

- Significantly improved performance of applying large quantities of
concurrent edits (e.g. when running "Replace all").
2024-07-16 15:53:29 +02:00
..
activity_indicator Make LSP task cancellation discoverable (#13226) 2024-06-18 12:44:35 -07:00
anthropic Make Claude 3.5 the default Anthropic model (#13324) 2024-06-21 18:47:38 +02:00
assets Move from Zed fonts to IBM Plex (#13596) 2024-06-27 14:36:44 -06:00
assistant Add an experimental, WIP diagnostics grouping panel (#14515) 2024-07-15 22:58:18 +03:00
assistant_slash_command Lay the groundwork for collaborating on assistant panel (#13991) 2024-07-10 17:36:22 +02:00
assistant_tooling Bring the Tool Calling README up to date (#11683) 2024-05-12 04:47:19 -07:00
audio Make tests less noisy (#12463) 2024-05-29 18:06:45 -07:00
auto_update auto-updates: Do not poll for updates on dev channel (#13311) 2024-06-20 15:00:54 +02:00
breadcrumbs Minor breadcrumb style updates (#14070) 2024-07-10 14:04:17 -04:00
call Remove never-used client parameter from message handler functions (#13406) 2024-06-22 16:07:36 -07:00
channel Remove never-used client parameter from message handler functions (#13406) 2024-06-22 16:07:36 -07:00
cli Stop relying on binary location to be in libexec on Linux (#13374) 2024-06-26 13:00:52 -06:00
client Extract a BufferStore object from Project (#14037) 2024-07-12 15:25:54 -07:00
clock Lay the groundwork for collaborating on assistant panel (#13991) 2024-07-10 17:36:22 +02:00
collab Introduce following for assistant panel (#14479) 2024-07-15 11:36:27 +02:00
collab_ui Introduce following for assistant panel (#14479) 2024-07-15 11:36:27 +02:00
collections gpui: Add SVG rendering to img element and generic asset cache (#9931) 2024-03-29 17:09:49 -07:00
command_palette Use UpdateGlobal accessors in more places (#11925) 2024-05-16 13:30:04 -04:00
command_palette_hooks Introduce InlineCompletionProvider (#9777) 2024-03-26 13:28:06 +01:00
copilot paths: Replace lazy_static! with OnceLock (#13213) 2024-06-18 12:22:37 -04:00
db paths: Replace lazy_static! with OnceLock (#13213) 2024-06-18 12:22:37 -04:00
dev_server_projects Remove never-used client parameter from message handler functions (#13406) 2024-06-22 16:07:36 -07:00
diagnostics Add an experimental, WIP diagnostics grouping panel (#14515) 2024-07-15 22:58:18 +03:00
editor editor: Improve performance of edit coalescing (#14567) 2024-07-16 15:53:29 +02:00
extension Allow Zed Nightly to use v0.0.7 of the Zed extension API (#14209) 2024-07-11 10:54:15 -04:00
extension_api zed_extension_api: Return structured slash command completions (#13879) 2024-07-05 14:08:42 -04:00
extension_cli extension_cli: Allow building without dynamically linking WebRTC (#13080) 2024-06-14 20:13:31 -04:00
extensions_ui extensions_ui: Remove commented-out code (#14525) 2024-07-15 19:00:49 -04:00
feature_flags Add an experimental, WIP diagnostics grouping panel (#14515) 2024-07-15 22:58:18 +03:00
feedback Refine inline transformation UX (#12939) 2024-06-13 08:35:22 +02:00
file_finder open picker (#14524) 2024-07-15 17:04:15 -06:00
file_icons Make tests less noisy (#12463) 2024-05-29 18:06:45 -07:00
fs Add support for projects managed with Yarn (#13644) 2024-07-11 14:56:07 +02:00
fsevent Retain run loop (#11241) 2024-04-30 23:31:59 -06:00
fuzzy Introduce an outline panel (#12637) 2024-06-12 23:22:52 +03:00
git Introduce an outline panel (#12637) 2024-06-12 23:22:52 +03:00
git_hosting_providers Extract http from util (#11680) 2024-05-10 15:50:20 -06:00
go_to_line Add more menus to Zed (#12940) 2024-06-18 12:16:54 -07:00
google_ai Respect requested gemini model (#13427) 2024-06-23 14:10:31 -06:00
gpui linux: Tweak file chooser dialogs (#14526) 2024-07-15 17:27:46 -07:00
gpui_macros Upsell built-in features on the extensions page (#14516) 2024-07-15 17:10:01 -04:00
headless Headless extensions (#14538) 2024-07-16 00:08:56 -06:00
html_to_markdown Publish html_to_markdown (#13718) 2024-07-01 17:18:58 -04:00
http zed_extension_api: Add github_release_by_tag_name (#12172) 2024-05-22 20:40:31 -04:00
image_viewer Make tests less noisy (#12463) 2024-05-29 18:06:45 -07:00
indexed_docs assistant: Add basic glob support for expanding items in /docs (#14370) 2024-07-12 17:57:50 -04:00
inline_completion_button Change the context menu and Copilot settings icon (#14501) 2024-07-16 09:40:40 -03:00
install_cli Fix flickering (#9012) 2024-03-11 10:45:57 +01:00
journal Add the ability for extensions to provide language settings (#10296) 2024-04-08 19:17:12 -04:00
language Introduce /symbols command in assistant panel (#14360) 2024-07-15 11:51:32 +02:00
language_selector Move Clippy configuration to the workspace level (#8891) 2024-03-05 12:01:17 -05:00
language_tools ui: Use PopoverMenu::new for constructing PopoverMenus (#13178) 2024-06-17 18:14:37 -04:00
languages rust: Expose import names in completions for modules and functions (#14490) 2024-07-15 14:26:39 +02:00
live_kit_client linux: Panic less on window init (#14255) 2024-07-11 16:04:46 -06:00
live_kit_server Vendor LiveKit protocol (#11672) 2024-05-10 14:18:40 -04:00
lsp Support dynamic formatting capabilities [un]registration (#14478) 2024-07-15 12:27:33 +03:00
markdown Selectable popover text (#12918) 2024-07-10 21:14:34 -06:00
markdown_preview Refine inline transformation UX (#12939) 2024-06-13 08:35:22 +02:00
media Revert "Revert "Revert dependency updates in #9836 (#10089)"" 2024-04-02 13:12:38 -06:00
menu open picker (#14524) 2024-07-15 17:04:15 -06:00
multi_buffer Add an experimental, WIP diagnostics grouping panel (#14515) 2024-07-15 22:58:18 +03:00
node_runtime JSON: Show package.json dependency tooltips on hover (#13481) 2024-06-25 14:59:29 +02:00
notifications Remove never-used client parameter from message handler functions (#13406) 2024-06-22 16:07:36 -07:00
ollama Allow Ollama Model KeepAlive to be None, defaulting to indefinite (#13059) 2024-06-14 10:33:28 -07:00
open_ai Change tool_calls to be an Option in response (#13778) 2024-07-03 11:07:11 -04:00
outline Add a way to filter items in the outline panel (#13984) 2024-07-09 16:44:24 +03:00
outline_panel Do not fold excerpts by default in the outline panel (#14378) 2024-07-13 04:08:21 +03:00
paths settings: Load .zed/settings.json even if .gitignored (#13370) 2024-06-21 18:39:14 +02:00
picker open picker (#14524) 2024-07-15 17:04:15 -06:00
prettier Lookup prettier more leniently (#14403) 2024-07-13 21:59:14 +03:00
project open picker (#14524) 2024-07-15 17:04:15 -06:00
project_panel project_panel: Fixed open in split not working in project panel (#14535) 2024-07-16 09:17:58 +03:00
project_symbols Add more menus to Zed (#12940) 2024-06-18 12:16:54 -07:00
proto Introduce following for assistant panel (#14479) 2024-07-15 11:36:27 +02:00
quick_action_bar Add REPL dropdown menu to toolbar (#14493) 2024-07-15 11:55:49 -07:00
recent_projects Selectable popover text (#12918) 2024-07-10 21:14:34 -06:00
refineable Move Clippy configuration to the workspace level (#8891) 2024-03-05 12:01:17 -05:00
release_channel auto-updates: Do not poll for updates on dev channel (#13311) 2024-06-20 15:00:54 +02:00
repl Switch to muted color for kernel output labels (#14529) 2024-07-15 18:20:45 -07:00
rich_text New revision of the Assistant Panel (#10870) 2024-04-23 16:23:26 -07:00
rope Indent guides (#11503) 2024-05-23 15:50:59 +02:00
rpc Extract a BufferStore object from Project (#14037) 2024-07-12 15:25:54 -07:00
search Add simple support for wrapscan (#13497) 2024-07-10 20:42:37 -06:00
semantic_index Refactor: Make it possible to share a remote worktree (#12775) 2024-06-07 12:53:01 -07:00
semantic_version Extract SemanticVersion into its own crate (#9956) 2024-03-29 12:11:57 -04:00
settings paths: Replace lazy_static! with OnceLock (#13213) 2024-06-18 12:22:37 -04:00
snippet html: Add support for autoclosing of tags (#11761) 2024-05-20 17:00:27 +02:00
snippet_provider extensions: Add support for snippets provided by extensions (#14020) 2024-07-10 09:40:50 +02:00
sqlez Remove extraneous Cargo.lock files (#14001) 2024-07-09 12:15:34 -04:00
sqlez_macros Dynamicer builds (#13074) 2024-06-21 16:32:32 -07:00
story Introduce a new markdown crate (#11556) 2024-05-09 11:03:33 +02:00
storybook linux: Panic less on window init (#14255) 2024-07-11 16:04:46 -06:00
sum_tree Introduce Editor::insert_flaps and Editor::remove_flaps (#12096) 2024-05-21 20:23:37 +02:00
supermaven Reduce spamming of inline completion discard events (#11999) 2024-05-17 16:37:17 -04:00
supermaven_api paths: Replace lazy_static! with OnceLock (#13213) 2024-06-18 12:22:37 -04:00
tab_switcher Introduce recent files ambient context for assistant (#11791) 2024-05-14 13:48:36 +02:00
task task: Add re-run task button to terminal title (#12379) 2024-05-29 11:40:43 +02:00
tasks_ui open picker (#14524) 2024-07-15 17:04:15 -06:00
telemetry_events Add metrics_id to editor_events (#13525) 2024-06-25 16:47:55 -04:00
terminal Revert hold: true for macOS tasks (#14376) 2024-07-13 04:02:38 +03:00
terminal_view Apply terminal.foreground and terminal.background from theme (#14281) 2024-07-13 14:41:44 +03:00
text Lay the groundwork for collaborating on assistant panel (#13991) 2024-07-10 17:36:22 +02:00
theme linux: Indicate when the window is focused (#14266) 2024-07-12 14:20:58 -07:00
theme_importer linux: Panic less on window init (#14255) 2024-07-11 16:04:46 -06:00
theme_selector Use UpdateGlobal accessors in more places (#11925) 2024-05-16 13:30:04 -04:00
time_format Inline git blame (#10398) 2024-04-15 14:21:52 +02:00
title_bar Introduce following for assistant panel (#14479) 2024-07-15 11:36:27 +02:00
ui Change the context menu and Copilot settings icon (#14501) 2024-07-16 09:40:40 -03:00
ui_input Rename ui_text_field crate to ui_input (#13949) 2024-07-08 17:05:30 -04:00
util Associate logs from log_err with the calling crate (#13617) 2024-06-27 17:03:47 -07:00
vcs_menu Adjust list item & pickers spacing (#14250) 2024-07-15 10:23:18 -03:00
vim vim: Add support for vim::PreviousLineStart motion (#14193) 2024-07-11 16:36:07 -06:00
welcome linux: Hide Install CLI from welcome (#14506) 2024-07-15 12:08:37 -06:00
workspace open picker (#14524) 2024-07-15 17:04:15 -06:00
worktree Extract a BufferStore object from Project (#14037) 2024-07-12 15:25:54 -07:00
zed Headless extensions (#14538) 2024-07-16 00:08:56 -06:00
zed_actions Add more menus to Zed (#12940) 2024-06-18 12:16:54 -07:00