mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-29 05:33:49 +00:00
Optimize two slow code paths (#2728)
Linear: https://linear.app/zed-industries/issue/Z-2578/zed-launches-very-slow-for-user I was searching for the cause of a slow startup time reported in the above issue, and I don't think I found it, but I did find two very noticeable slow code paths while profiling, and fixed them. ### Notes 1. When starting the JSON language server, we provide it with a JSON schema for our settings. For the `theme` setting, the JSON schema needs to read all of the themes in the registry, to generate a list of valid theme names. Previously, as part of this, we were deserializing each theme from JSON, which took a lot of CPU. Now, we don't do that. 2. When an FS event occurs within a git repository, we reload the git status for all entries in that git repository. Previously, we did that via a separate `libgit2` call per FS entry (including ignored entries, so many thousands in the case of the `zed` repo). Now we do one `libgit2` call, asking for all of the statuses. Git carries an index of all of the files with statuses, so this is fast. Release Notes: - Improved the the performance of starting up a JSON language server. - Improved the performance of handling changes to git repositories, such as changing branches or committing.
This commit is contained in:
commit
dcc2cd8dff
4 changed files with 25 additions and 11 deletions
|
@ -33,6 +33,7 @@ pub trait GitRepository: Send {
|
|||
fn statuses(&self) -> Option<TreeMap<RepoPath, GitFileStatus>>;
|
||||
|
||||
fn status(&self, path: &RepoPath) -> Result<Option<GitFileStatus>>;
|
||||
|
||||
fn branches(&self) -> Result<Vec<Branch>> {
|
||||
Ok(vec![])
|
||||
}
|
||||
|
|
|
@ -2023,6 +2023,9 @@ impl LocalSnapshot {
|
|||
) -> Vec<Arc<Path>> {
|
||||
let mut changes = vec![];
|
||||
let mut edits = vec![];
|
||||
|
||||
let statuses = repo_ptr.statuses();
|
||||
|
||||
for mut entry in self
|
||||
.descendent_entries(false, false, &work_directory.0)
|
||||
.cloned()
|
||||
|
@ -2030,10 +2033,8 @@ impl LocalSnapshot {
|
|||
let Ok(repo_path) = entry.path.strip_prefix(&work_directory.0) else {
|
||||
continue;
|
||||
};
|
||||
let git_file_status = repo_ptr
|
||||
.status(&RepoPath(repo_path.into()))
|
||||
.log_err()
|
||||
.flatten();
|
||||
let repo_path = RepoPath(repo_path.to_path_buf());
|
||||
let git_file_status = statuses.as_ref().and_then(|s| s.get(&repo_path).copied());
|
||||
if entry.git_status != git_file_status {
|
||||
entry.git_status = git_file_status;
|
||||
changes.push(entry.path.clone());
|
||||
|
|
|
@ -5,6 +5,7 @@ use parking_lot::Mutex;
|
|||
use serde::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
collections::HashMap,
|
||||
sync::{
|
||||
atomic::{AtomicUsize, Ordering::SeqCst},
|
||||
|
@ -43,7 +44,7 @@ impl ThemeRegistry {
|
|||
this
|
||||
}
|
||||
|
||||
pub fn list(&self, staff: bool) -> impl Iterator<Item = ThemeMeta> + '_ {
|
||||
pub fn list_names(&self, staff: bool) -> impl Iterator<Item = Cow<str>> + '_ {
|
||||
let mut dirs = self.assets.list("themes/");
|
||||
|
||||
if !staff {
|
||||
|
@ -53,10 +54,21 @@ impl ThemeRegistry {
|
|||
.collect()
|
||||
}
|
||||
|
||||
dirs.into_iter().filter_map(|path| {
|
||||
let filename = path.strip_prefix("themes/")?;
|
||||
let theme_name = filename.strip_suffix(".json")?;
|
||||
self.get(theme_name).ok().map(|theme| theme.meta.clone())
|
||||
fn get_name(path: &str) -> Option<&str> {
|
||||
path.strip_prefix("themes/")?.strip_suffix(".json")
|
||||
}
|
||||
|
||||
dirs.into_iter().filter_map(|path| match path {
|
||||
Cow::Borrowed(path) => Some(Cow::Borrowed(get_name(path)?)),
|
||||
Cow::Owned(path) => Some(Cow::Owned(get_name(&path)?.to_string())),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn list(&self, staff: bool) -> impl Iterator<Item = ThemeMeta> + '_ {
|
||||
self.list_names(staff).filter_map(|theme_name| {
|
||||
self.get(theme_name.as_ref())
|
||||
.ok()
|
||||
.map(|theme| theme.meta.clone())
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -178,8 +178,8 @@ impl settings::Setting for ThemeSettings {
|
|||
let mut root_schema = generator.root_schema_for::<ThemeSettingsContent>();
|
||||
let theme_names = cx
|
||||
.global::<Arc<ThemeRegistry>>()
|
||||
.list(params.staff_mode)
|
||||
.map(|theme| Value::String(theme.name.clone()))
|
||||
.list_names(params.staff_mode)
|
||||
.map(|theme_name| Value::String(theme_name.to_string()))
|
||||
.collect();
|
||||
|
||||
let theme_name_schema = SchemaObject {
|
||||
|
|
Loading…
Reference in a new issue