From 3aaf07b8cb9a17669894db9f3e6afdb302676fdb Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 10 Jun 2021 23:03:16 +0300 Subject: Add more profiling for flyimports --- crates/hir_def/src/import_map.rs | 153 +++++++++++++++++++++------------------ crates/hir_def/src/lang_item.rs | 1 + crates/hir_def/src/per_ns.rs | 2 + 3 files changed, 85 insertions(+), 71 deletions(-) (limited to 'crates/hir_def') diff --git a/crates/hir_def/src/import_map.rs b/crates/hir_def/src/import_map.rs index 960cabb5f..2055edc95 100644 --- a/crates/hir_def/src/import_map.rs +++ b/crates/hir_def/src/import_map.rs @@ -69,80 +69,10 @@ pub struct ImportMap { impl ImportMap { pub fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc { let _p = profile::span("import_map_query"); - let def_map = db.crate_def_map(krate); - let mut import_map = Self::default(); - - // We look only into modules that are public(ly reexported), starting with the crate root. - let empty = ImportPath { segments: vec![] }; - let root = def_map.module_id(def_map.root()); - let mut worklist = vec![(root, empty)]; - while let Some((module, mod_path)) = worklist.pop() { - let ext_def_map; - let mod_data = if module.krate == krate { - &def_map[module.local_id] - } else { - // The crate might reexport a module defined in another crate. - ext_def_map = module.def_map(db); - &ext_def_map[module.local_id] - }; - - let visible_items = mod_data.scope.entries().filter_map(|(name, per_ns)| { - let per_ns = per_ns.filter_visibility(|vis| vis == Visibility::Public); - if per_ns.is_none() { - None - } else { - Some((name, per_ns)) - } - }); - for (name, per_ns) in visible_items { - let mk_path = || { - let mut path = mod_path.clone(); - path.segments.push(name.clone()); - path - }; - - for item in per_ns.iter_items() { - let path = mk_path(); - let path_len = path.len(); - let import_info = - ImportInfo { path, container: module, is_trait_assoc_item: false }; - - if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() { - import_map.collect_trait_assoc_items( - db, - tr, - matches!(item, ItemInNs::Types(_)), - &import_info, - ); - } - - match import_map.map.entry(item) { - Entry::Vacant(entry) => { - entry.insert(import_info); - } - Entry::Occupied(mut entry) => { - // If the new path is shorter, prefer that one. - if path_len < entry.get().path.len() { - *entry.get_mut() = import_info; - } else { - continue; - } - } - } - - // If we've just added a path to a module, descend into it. We might traverse - // modules multiple times, but only if the new path to it is shorter than the - // first (else we `continue` above). - if let Some(ModuleDefId::ModuleId(mod_id)) = item.as_module_def_id() { - worklist.push((mod_id, mk_path())); - } - } - } - } + let mut import_map = collect_import_map(db, krate); let mut importables = import_map.map.iter().collect::>(); - importables.sort_by(cmp); // Build the FST, taking care not to insert duplicate values. @@ -185,6 +115,7 @@ impl ImportMap { is_type_in_ns: bool, original_import_info: &ImportInfo, ) { + let _p = profile::span("collect_trait_assoc_items"); for (assoc_item_name, item) in &db.trait_data(tr).items { let module_def_id = match item { AssocItemId::FunctionId(f) => ModuleDefId::from(*f), @@ -210,6 +141,84 @@ impl ImportMap { } } +fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMap { + let _p = profile::span("collect_import_map"); + + let def_map = db.crate_def_map(krate); + let mut import_map = ImportMap::default(); + + // We look only into modules that are public(ly reexported), starting with the crate root. + let empty = ImportPath { segments: vec![] }; + let root = def_map.module_id(def_map.root()); + let mut worklist = vec![(root, empty)]; + while let Some((module, mod_path)) = worklist.pop() { + let ext_def_map; + let mod_data = if module.krate == krate { + &def_map[module.local_id] + } else { + // The crate might reexport a module defined in another crate. + ext_def_map = module.def_map(db); + &ext_def_map[module.local_id] + }; + + let visible_items = mod_data.scope.entries().filter_map(|(name, per_ns)| { + let per_ns = per_ns.filter_visibility(|vis| vis == Visibility::Public); + if per_ns.is_none() { + None + } else { + Some((name, per_ns)) + } + }); + + for (name, per_ns) in visible_items { + let mk_path = || { + let mut path = mod_path.clone(); + path.segments.push(name.clone()); + path + }; + + for item in per_ns.iter_items() { + let path = mk_path(); + let path_len = path.len(); + let import_info = + ImportInfo { path, container: module, is_trait_assoc_item: false }; + + if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() { + import_map.collect_trait_assoc_items( + db, + tr, + matches!(item, ItemInNs::Types(_)), + &import_info, + ); + } + + match import_map.map.entry(item) { + Entry::Vacant(entry) => { + entry.insert(import_info); + } + Entry::Occupied(mut entry) => { + // If the new path is shorter, prefer that one. + if path_len < entry.get().path.len() { + *entry.get_mut() = import_info; + } else { + continue; + } + } + } + + // If we've just added a path to a module, descend into it. We might traverse + // modules multiple times, but only if the new path to it is shorter than the + // first (else we `continue` above). + if let Some(ModuleDefId::ModuleId(mod_id)) = item.as_module_def_id() { + worklist.push((mod_id, mk_path())); + } + } + } + } + + import_map +} + impl PartialEq for ImportMap { fn eq(&self, other: &Self) -> bool { // `fst` and `importables` are built from `map`, so we don't need to compare them. @@ -240,6 +249,7 @@ impl fmt::Debug for ImportMap { } fn fst_path(path: &ImportPath) -> String { + let _p = profile::span("fst_path"); let mut s = path.to_string(); s.make_ascii_lowercase(); s @@ -338,6 +348,7 @@ impl Query { } fn import_matches(&self, import: &ImportInfo, enforce_lowercase: bool) -> bool { + let _p = profile::span("import_map::Query::import_matches"); if import.is_trait_assoc_item { if self.exclude_import_kinds.contains(&ImportKind::AssociatedItem) { return false; diff --git a/crates/hir_def/src/lang_item.rs b/crates/hir_def/src/lang_item.rs index 9e90f745c..3a45cbfa1 100644 --- a/crates/hir_def/src/lang_item.rs +++ b/crates/hir_def/src/lang_item.rs @@ -141,6 +141,7 @@ impl LangItems { ) where T: Into + Copy, { + let _p = profile::span("collect_lang_item"); if let Some(lang_item_name) = lang_attr(db, item) { self.items.entry(lang_item_name).or_insert_with(|| constructor(item)); } diff --git a/crates/hir_def/src/per_ns.rs b/crates/hir_def/src/per_ns.rs index a594afce6..a9f13cb82 100644 --- a/crates/hir_def/src/per_ns.rs +++ b/crates/hir_def/src/per_ns.rs @@ -62,6 +62,7 @@ impl PerNs { } pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs { + let _p = profile::span("PerNs::filter_visibility"); PerNs { types: self.types.filter(|(_, v)| f(*v)), values: self.values.filter(|(_, v)| f(*v)), @@ -86,6 +87,7 @@ impl PerNs { } pub fn iter_items(self) -> impl Iterator { + let _p = profile::span("PerNs::iter_items"); self.types .map(|it| ItemInNs::Types(it.0)) .into_iter() -- cgit v1.2.3