ZIm/crates
Max Brunsfeld f128cf4a33
Defer scanning some worktree subdirectories until they are expanded in the project panel (#2622)
Closes
https://linear.app/zed-industries/issue/Z-352/high-memory-usage-from-fs-scanning-if-project-contains-symlinks-that

### Background

Currently, when you open a project, Zed eagerly scans the directory,
building an in-memory representation of all of the files and directories
within. This scanning includes all git-ignored files and follows any
symlinks. When any directory changes on disk, Zed recursively rescans it
in order to keep its in-memory representation up-to-date. When
collaborating, all of these files are replicated to all guests.

Right now, there are some performance problems associated with the
maintenance of this filesystem state:
* For various reasons, some projects contain symlinks that point out to
large folders like `$HOME`, which itself contains many symlinks that
point to the same large directory. When these projects are opened, the
worktree scans endlessly, using more and more memory.
* Some git-ignored directories (like `target` in a rust project) contain
*many* more files than are actually tracked in the git repository. These
files often change as a result of saving, (e.g. because the compiler
runs). Maintaining in memory all of these paths isn't useful to the
user, and causes significant CPU usage on every save. Most importantly,
when collaborating sending all of these changes to guests can be slow,
and can delay all other RPC messages.

### Change

This PR changes the worktree's filesystem-scanning logic to be *lazy*
about scanning two types of directories:
* git ignored directories
* "external" directories (those that are canonically located outside of
the worktree root, but accessed via symlinks)

The laziness works as follows. When, during a recursive scan, a
directory is found that falls into one of the above 2 categories, that
directory is marked as "unloaded". The directory might later be scanned,
if some explicit operation is performed within it (like opening a
buffer, or creating a file), if any collaborator expands that directory
in their project panel, or if an LSP requests that it be watched.

### Results

When collaborating on the `zed` folder:

| metric | before | after |
|-------|--------|------|
| # `worktree_entries` in collab db initially | 154,763 |  77,679 |
| # `worktree_entries` in collab db after 5 saves | 181,952 | 77,679
(nothing new to scan) |
| app memory footprint (host) | 260MB | 228.5 MB  |

The db thing is a win, because reading and writing to the
`worktree_entries` table is one of the most expensive thing that the
`collab` server does.

There's also generally lower background CPU usage after every save,
because we don't need to recursively rescan directories inside of
`target`.

### Limitations

We still end up scanning some unnecessary directories (like
`target/debug/build/zed-b612db829aeac16e/out`) because the LSP instructs
us to watch those.

### To do:

* [x] Expand parent directories of any path opened via LSP
* [x] Avoid creating orphaned entries when FS events happen inside of
unscanned directories
* [x] Scan any newly-non-ignored directories after gitignore changes
* [x] Emit correct events for newly-discovered paths when expanding dirs
* [x] GC the set of expanded directory ids when dirs are removed
* [x] Don't include "external" entries in file-finder
* [x] Expand any directories watched by LSP
* [ ] manual testing and profiling

### Release Notes:

- Fixed a bug where Zed would use excessive memory when a project folder
contained symlinks pointing to directories outside of the project.
- Reduced Zed's memory and CPU usage when working in folders containing
many git-ignored files.
2023-06-27 17:07:23 -07:00
..
activity_indicator Fix up toggles 2023-06-20 16:05:23 -07:00
ai Remove assistant panel zoom test 2023-06-26 19:10:59 +02:00
auto_update Split out Interactive<T> into Toggle<T> and Interactive<T> 2023-06-20 16:05:20 -07:00
breadcrumbs Split out Interactive<T> into Toggle<T> and Interactive<T> 2023-06-20 16:05:20 -07:00
call 🎨 Specify more dependencies at the workspace level 2023-04-24 17:41:55 -07:00
cli Fix typos 2023-06-02 22:02:19 -04:00
client Add installation_id to panic events 2023-06-23 21:02:01 -04:00
clock Fixed a bug where buffer saved clocks would desynchronize in rare execution paths 2023-06-07 16:10:45 -07:00
collab Get integration test passing. Wait for expand entry on remote projects. 2023-06-22 10:34:28 -07:00
collab_ui Adjust some of the styles to the new Toggleable format 2023-06-20 16:05:23 -07:00
collections Move command palette filter into collections crate 2023-03-28 20:13:17 -07:00
command_palette Fix up toggles 2023-06-20 16:05:23 -07:00
context_menu Remove unescessary enum 2023-06-20 16:05:23 -07:00
copilot Split out Interactive<T> into Toggle<T> and Interactive<T> 2023-06-20 16:05:20 -07:00
copilot_button Split out Interactive<T> into Toggle<T> and Interactive<T> 2023-06-20 16:05:20 -07:00
db WIP 2023-05-22 23:11:27 -06:00
diagnostics Split Interactive into Interactive and Toggleable (#2628) 2023-06-21 15:03:08 -04:00
drag_and_drop Prevent some cases of clipping icons due to pixel coord rounding 2023-05-08 11:42:00 -04:00
editor vim: Fix scrolling (#2647) 2023-06-27 04:01:14 -06:00
feedback Split out Interactive<T> into Toggle<T> and Interactive<T> 2023-06-20 16:05:20 -07:00
file_finder Split out Interactive<T> into Toggle<T> and Interactive<T> 2023-06-20 16:05:20 -07:00
fs Fix expansion of ancestor directories when refreshing a path 2023-06-22 10:34:28 -07:00
fsevent 🎨 Specify more dependencies at the workspace level 2023-04-24 17:41:55 -07:00
fuzzy remove commented line 2023-02-27 12:06:10 -08:00
git Clean up final remaining code paths calling old diff update method 2023-05-25 14:41:09 -04:00
go_to_line Enable test-support on editor in tests 2023-05-20 09:54:38 -06:00
gpui Add assistant icons to the toolbar 2023-06-26 16:49:33 +02:00
gpui_macros Add a derive macro for Element 2023-06-25 07:51:50 -06:00
install_cli 🎨 Specify more dependencies at the workspace level 2023-04-24 17:41:55 -07:00
journal Enable test-support on editor in tests 2023-05-20 09:54:38 -06:00
language Fix bugs in handling combined injections exposed by HEEx 2023-06-27 15:08:26 -07:00
language_selector Split out Interactive<T> into Toggle<T> and Interactive<T> 2023-06-20 16:05:20 -07:00
language_tools Split out Interactive<T> into Toggle<T> and Interactive<T> 2023-06-20 16:05:20 -07:00
live_kit_client Implement test stubs 2023-06-15 19:28:59 -07:00
live_kit_server 🎨 Specify more dependencies at the workspace level 2023-04-24 17:41:55 -07:00
lsp Run LSP response deserialization outside of main thread 2023-06-21 13:20:42 +03:00
media Update rust-bindgen dev-dependencies 2023-06-04 23:34:22 -04:00
menu Remove internal actions from menu crate 2023-04-27 14:29:11 +02:00
node_runtime Source ESLint server from Github rather than 3rd party NPM package 2023-04-28 16:42:36 -04:00
outline Split out Interactive<T> into Toggle<T> and Interactive<T> 2023-06-20 16:05:20 -07:00
picker Enable test-support on editor in tests 2023-05-20 09:54:38 -06:00
plugin 🎨 Specify more dependencies at the workspace level 2023-04-24 17:41:55 -07:00
plugin_macros Fix typos 2023-06-02 22:02:19 -04:00
plugin_runtime Fix typos 2023-06-02 22:02:19 -04:00
project Use FakeFs in worktree gitignore test 2023-06-27 15:40:36 -07:00
project_panel Defer scanning some worktree subdirectories until they are expanded in the project panel (#2622) 2023-06-27 17:07:23 -07:00
project_symbols Rename on/off states to active/inactive 2023-06-20 16:05:23 -07:00
recent_projects Split out Interactive<T> into Toggle<T> and Interactive<T> 2023-06-20 16:05:20 -07:00
rope Rename SumTree::push_tree to ::append 2023-06-19 19:49:33 -06:00
rpc Get integration test passing. Wait for expand entry on remote projects. 2023-06-22 10:34:28 -07:00
search Re-enable buffer search in assistant 2023-06-23 09:57:31 +02:00
settings Revert "Panic in debug if global settings can't be deserialized from defaults" 2023-06-26 16:03:19 +02:00
snippet 🎨 Specify more dependencies at the workspace level 2023-04-24 17:41:55 -07:00
sqlez Fix typos 2023-06-02 22:02:19 -04:00
sqlez_macros 🎨 Specify more dependencies at the workspace level 2023-04-24 17:41:55 -07:00
staff_mode 🎨 Specify more dependencies at the workspace level 2023-04-24 17:41:55 -07:00
sum_tree Rename SumTree::push_tree to ::append 2023-06-19 19:49:33 -06:00
terminal Fix typos 2023-06-02 22:02:19 -04:00
terminal_view Remove the nested Pane from the assistant 2023-06-20 18:52:48 -06:00
text Rename SumTree::push_tree to ::append 2023-06-19 19:49:33 -06:00
theme Add hover state to assistant buttons 2023-06-26 17:48:43 +02:00
theme_selector Split out Interactive<T> into Toggle<T> and Interactive<T> 2023-06-20 16:05:20 -07:00
util Save conversations to ~/.config/zed/conversations 2023-06-16 16:15:07 -06:00
vim vim: indent/outdent (#2644) 2023-06-27 04:15:55 -06:00
welcome Split out Interactive<T> into Toggle<T> and Interactive<T> 2023-06-20 16:05:20 -07:00
workspace Re-enable buffer search in assistant 2023-06-23 09:57:31 +02:00
xtask Fixup xtask compilation 2023-06-22 18:06:52 +02:00
zed Fix bugs in handling combined injections exposed by HEEx (#2652) 2023-06-27 15:17:29 -07:00