]> git.lizzy.rs Git - rust.git/commitdiff
Add more profiling for flyimports
authorKirill Bulatov <mail4score@gmail.com>
Thu, 10 Jun 2021 20:03:16 +0000 (23:03 +0300)
committerKirill Bulatov <mail4score@gmail.com>
Thu, 10 Jun 2021 20:43:46 +0000 (23:43 +0300)
crates/base_db/src/lib.rs
crates/hir/src/lib.rs
crates/hir_def/src/import_map.rs
crates/hir_def/src/lang_item.rs
crates/hir_def/src/per_ns.rs
crates/ide_db/src/symbol_index.rs

index 62bf2a4b2c1f84a45c6efbf2045f8ce925ce45a3..54baa3a63305a40f8bd55dd04011345f2533c820 100644 (file)
@@ -120,6 +120,7 @@ fn resolve_path(&self, path: AnchoredPath) -> Option<FileId> {
     }
 
     fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
+        let _p = profile::span("relevant_crates");
         let source_root = self.0.file_source_root(file_id);
         self.0.source_root_crates(source_root)
     }
index debc3ee624c069be28ca25bab988ff316435ab86..b9c1dc44df0806bf738a6340726dde4e79b3dfaa 100644 (file)
@@ -191,6 +191,7 @@ pub fn query_external_importables(
         db: &dyn DefDatabase,
         query: import_map::Query,
     ) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> {
+        let _p = profile::span("query_external_importables");
         import_map::search_dependencies(db, self.into(), query).into_iter().map(|item| match item {
             ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id.into()),
             ItemInNs::Macros(mac_id) => Either::Right(mac_id.into()),
@@ -2185,6 +2186,7 @@ pub fn iterate_method_candidates<T>(
         name: Option<&Name>,
         mut callback: impl FnMut(&Ty, Function) -> Option<T>,
     ) -> Option<T> {
+        let _p = profile::span("iterate_method_candidates");
         // There should be no inference vars in types passed here
         // FIXME check that?
         // FIXME replace Unknown by bound vars here
@@ -2218,6 +2220,7 @@ pub fn iterate_path_candidates<T>(
         name: Option<&Name>,
         mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
     ) -> Option<T> {
+        let _p = profile::span("iterate_path_candidates");
         let canonical = hir_ty::replace_errors_with_variables(&self.ty);
 
         let env = self.env.clone();
@@ -2255,6 +2258,7 @@ pub fn applicable_inherent_traits<'a>(
         &'a self,
         db: &'a dyn HirDatabase,
     ) -> impl Iterator<Item = Trait> + 'a {
+        let _p = profile::span("applicable_inherent_traits");
         self.autoderef(db)
             .filter_map(|derefed_type| derefed_type.ty.dyn_trait())
             .flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db.upcast(), dyn_trait_id))
index 960cabb5fd480ea82261a34b1e9d46d03060d639..2055edc95af0e02f0258f076c640a0c49fc86e63 100644 (file)
@@ -69,80 +69,10 @@ pub struct ImportMap {
 impl ImportMap {
     pub fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<Self> {
         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::<Vec<_>>();
-
         importables.sort_by(cmp);
 
         // Build the FST, taking care not to insert duplicate values.
@@ -185,6 +115,7 @@ fn collect_trait_assoc_items(
         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 @@ fn collect_trait_assoc_items(
     }
 }
 
+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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 }
 
 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 @@ pub fn exclude_import_kind(mut self, import_kind: ImportKind) -> Self {
     }
 
     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;
index 9e90f745ce285b6455e1801e8d93e7b056d28af7..3a45cbfa1217855a368588441fe42c61b4175b31 100644 (file)
@@ -141,6 +141,7 @@ fn collect_lang_item<T>(
     ) where
         T: Into<AttrDefId> + 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));
         }
index a594afce6686761f409ad25fdd4832cb61139596..a9f13cb82085ec4346531d98a08a8627d8e4be65 100644 (file)
@@ -62,6 +62,7 @@ pub fn take_macros(self) -> Option<MacroDefId> {
     }
 
     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 @@ pub fn or(self, other: PerNs) -> PerNs {
     }
 
     pub fn iter_items(self) -> impl Iterator<Item = ItemInNs> {
+        let _p = profile::span("PerNs::iter_items");
         self.types
             .map(|it| ItemInNs::Types(it.0))
             .into_iter()
index 5c372a7e5e371b517c18661cd4b3eaaca39d01c9..000f87a8588c2b870d5397e3f51ac608fdce90bb 100644 (file)
@@ -197,6 +197,7 @@ pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> {
 }
 
 pub fn crate_symbols(db: &RootDatabase, krate: CrateId, query: Query) -> Vec<FileSymbol> {
+    let _p = profile::span("crate_symbols").detail(|| format!("{:?}", query));
     // FIXME(#4842): This now depends on CrateDefMap, why not build the entire symbol index from
     // that instead?
 
@@ -321,6 +322,7 @@ fn map_value_to_range(value: u64) -> (usize, usize) {
 
 impl Query {
     pub(crate) fn search(self, indices: &[&SymbolIndex]) -> Vec<FileSymbol> {
+        let _p = profile::span("symbol_index::Query::search");
         let mut op = fst::map::OpBuilder::new();
         for file_symbols in indices.iter() {
             let automaton = fst::automaton::Subsequence::new(&self.lowercased);