Add more profiling for flyimports
This commit is contained in:
parent
f4da4de7cd
commit
3aaf07b8cb
@ -120,6 +120,7 @@ impl<T: SourceDatabaseExt> FileLoader for FileLoaderDelegate<&'_ T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
|
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);
|
let source_root = self.0.file_source_root(file_id);
|
||||||
self.0.source_root_crates(source_root)
|
self.0.source_root_crates(source_root)
|
||||||
}
|
}
|
||||||
|
@ -191,6 +191,7 @@ impl Crate {
|
|||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
query: import_map::Query,
|
query: import_map::Query,
|
||||||
) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> {
|
) -> 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 {
|
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::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id.into()),
|
||||||
ItemInNs::Macros(mac_id) => Either::Right(mac_id.into()),
|
ItemInNs::Macros(mac_id) => Either::Right(mac_id.into()),
|
||||||
@ -2185,6 +2186,7 @@ impl Type {
|
|||||||
name: Option<&Name>,
|
name: Option<&Name>,
|
||||||
mut callback: impl FnMut(&Ty, Function) -> Option<T>,
|
mut callback: impl FnMut(&Ty, Function) -> Option<T>,
|
||||||
) -> Option<T> {
|
) -> Option<T> {
|
||||||
|
let _p = profile::span("iterate_method_candidates");
|
||||||
// There should be no inference vars in types passed here
|
// There should be no inference vars in types passed here
|
||||||
// FIXME check that?
|
// FIXME check that?
|
||||||
// FIXME replace Unknown by bound vars here
|
// FIXME replace Unknown by bound vars here
|
||||||
@ -2218,6 +2220,7 @@ impl Type {
|
|||||||
name: Option<&Name>,
|
name: Option<&Name>,
|
||||||
mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
|
mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
|
||||||
) -> Option<T> {
|
) -> Option<T> {
|
||||||
|
let _p = profile::span("iterate_path_candidates");
|
||||||
let canonical = hir_ty::replace_errors_with_variables(&self.ty);
|
let canonical = hir_ty::replace_errors_with_variables(&self.ty);
|
||||||
|
|
||||||
let env = self.env.clone();
|
let env = self.env.clone();
|
||||||
@ -2255,6 +2258,7 @@ impl Type {
|
|||||||
&'a self,
|
&'a self,
|
||||||
db: &'a dyn HirDatabase,
|
db: &'a dyn HirDatabase,
|
||||||
) -> impl Iterator<Item = Trait> + 'a {
|
) -> impl Iterator<Item = Trait> + 'a {
|
||||||
|
let _p = profile::span("applicable_inherent_traits");
|
||||||
self.autoderef(db)
|
self.autoderef(db)
|
||||||
.filter_map(|derefed_type| derefed_type.ty.dyn_trait())
|
.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))
|
.flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db.upcast(), dyn_trait_id))
|
||||||
|
@ -69,8 +69,83 @@ pub struct ImportMap {
|
|||||||
impl ImportMap {
|
impl ImportMap {
|
||||||
pub fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<Self> {
|
pub fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<Self> {
|
||||||
let _p = profile::span("import_map_query");
|
let _p = profile::span("import_map_query");
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
let mut builder = fst::MapBuilder::memory();
|
||||||
|
let mut last_batch_start = 0;
|
||||||
|
|
||||||
|
for idx in 0..importables.len() {
|
||||||
|
if let Some(next_item) = importables.get(idx + 1) {
|
||||||
|
if cmp(&importables[last_batch_start], next_item) == Ordering::Equal {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let key = fst_path(&importables[last_batch_start].1.path);
|
||||||
|
builder.insert(key, last_batch_start as u64).unwrap();
|
||||||
|
|
||||||
|
last_batch_start = idx + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
import_map.fst = fst::Map::new(builder.into_inner().unwrap()).unwrap();
|
||||||
|
import_map.importables = importables.iter().map(|(item, _)| **item).collect();
|
||||||
|
|
||||||
|
Arc::new(import_map)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the `ModPath` needed to import/mention `item`, relative to this crate's root.
|
||||||
|
pub fn path_of(&self, item: ItemInNs) -> Option<&ImportPath> {
|
||||||
|
self.import_info_for(item).map(|it| &it.path)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn import_info_for(&self, item: ItemInNs) -> Option<&ImportInfo> {
|
||||||
|
self.map.get(&item)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_trait_assoc_items(
|
||||||
|
&mut self,
|
||||||
|
db: &dyn DefDatabase,
|
||||||
|
tr: TraitId,
|
||||||
|
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),
|
||||||
|
AssocItemId::ConstId(c) => ModuleDefId::from(*c),
|
||||||
|
// cannot use associated type aliases directly: need a `<Struct as Trait>::TypeAlias`
|
||||||
|
// qualifier, ergo no need to store it for imports in import_map
|
||||||
|
AssocItemId::TypeAliasId(_) => {
|
||||||
|
cov_mark::hit!(type_aliases_ignored);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let assoc_item = if is_type_in_ns {
|
||||||
|
ItemInNs::Types(module_def_id)
|
||||||
|
} else {
|
||||||
|
ItemInNs::Values(module_def_id)
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut assoc_item_info = original_import_info.clone();
|
||||||
|
assoc_item_info.path.segments.push(assoc_item_name.to_owned());
|
||||||
|
assoc_item_info.is_trait_assoc_item = true;
|
||||||
|
self.map.insert(assoc_item, assoc_item_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 def_map = db.crate_def_map(krate);
|
||||||
let mut import_map = Self::default();
|
let mut import_map = ImportMap::default();
|
||||||
|
|
||||||
// We look only into modules that are public(ly reexported), starting with the crate root.
|
// We look only into modules that are public(ly reexported), starting with the crate root.
|
||||||
let empty = ImportPath { segments: vec![] };
|
let empty = ImportPath { segments: vec![] };
|
||||||
@ -141,73 +216,7 @@ impl ImportMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut importables = import_map.map.iter().collect::<Vec<_>>();
|
import_map
|
||||||
|
|
||||||
importables.sort_by(cmp);
|
|
||||||
|
|
||||||
// Build the FST, taking care not to insert duplicate values.
|
|
||||||
|
|
||||||
let mut builder = fst::MapBuilder::memory();
|
|
||||||
let mut last_batch_start = 0;
|
|
||||||
|
|
||||||
for idx in 0..importables.len() {
|
|
||||||
if let Some(next_item) = importables.get(idx + 1) {
|
|
||||||
if cmp(&importables[last_batch_start], next_item) == Ordering::Equal {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let key = fst_path(&importables[last_batch_start].1.path);
|
|
||||||
builder.insert(key, last_batch_start as u64).unwrap();
|
|
||||||
|
|
||||||
last_batch_start = idx + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
import_map.fst = fst::Map::new(builder.into_inner().unwrap()).unwrap();
|
|
||||||
import_map.importables = importables.iter().map(|(item, _)| **item).collect();
|
|
||||||
|
|
||||||
Arc::new(import_map)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the `ModPath` needed to import/mention `item`, relative to this crate's root.
|
|
||||||
pub fn path_of(&self, item: ItemInNs) -> Option<&ImportPath> {
|
|
||||||
self.import_info_for(item).map(|it| &it.path)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn import_info_for(&self, item: ItemInNs) -> Option<&ImportInfo> {
|
|
||||||
self.map.get(&item)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn collect_trait_assoc_items(
|
|
||||||
&mut self,
|
|
||||||
db: &dyn DefDatabase,
|
|
||||||
tr: TraitId,
|
|
||||||
is_type_in_ns: bool,
|
|
||||||
original_import_info: &ImportInfo,
|
|
||||||
) {
|
|
||||||
for (assoc_item_name, item) in &db.trait_data(tr).items {
|
|
||||||
let module_def_id = match item {
|
|
||||||
AssocItemId::FunctionId(f) => ModuleDefId::from(*f),
|
|
||||||
AssocItemId::ConstId(c) => ModuleDefId::from(*c),
|
|
||||||
// cannot use associated type aliases directly: need a `<Struct as Trait>::TypeAlias`
|
|
||||||
// qualifier, ergo no need to store it for imports in import_map
|
|
||||||
AssocItemId::TypeAliasId(_) => {
|
|
||||||
cov_mark::hit!(type_aliases_ignored);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let assoc_item = if is_type_in_ns {
|
|
||||||
ItemInNs::Types(module_def_id)
|
|
||||||
} else {
|
|
||||||
ItemInNs::Values(module_def_id)
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut assoc_item_info = original_import_info.clone();
|
|
||||||
assoc_item_info.path.segments.push(assoc_item_name.to_owned());
|
|
||||||
assoc_item_info.is_trait_assoc_item = true;
|
|
||||||
self.map.insert(assoc_item, assoc_item_info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for ImportMap {
|
impl PartialEq for ImportMap {
|
||||||
@ -240,6 +249,7 @@ impl fmt::Debug for ImportMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn fst_path(path: &ImportPath) -> String {
|
fn fst_path(path: &ImportPath) -> String {
|
||||||
|
let _p = profile::span("fst_path");
|
||||||
let mut s = path.to_string();
|
let mut s = path.to_string();
|
||||||
s.make_ascii_lowercase();
|
s.make_ascii_lowercase();
|
||||||
s
|
s
|
||||||
@ -338,6 +348,7 @@ impl Query {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn import_matches(&self, import: &ImportInfo, enforce_lowercase: bool) -> bool {
|
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 import.is_trait_assoc_item {
|
||||||
if self.exclude_import_kinds.contains(&ImportKind::AssociatedItem) {
|
if self.exclude_import_kinds.contains(&ImportKind::AssociatedItem) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -141,6 +141,7 @@ impl LangItems {
|
|||||||
) where
|
) where
|
||||||
T: Into<AttrDefId> + Copy,
|
T: Into<AttrDefId> + Copy,
|
||||||
{
|
{
|
||||||
|
let _p = profile::span("collect_lang_item");
|
||||||
if let Some(lang_item_name) = lang_attr(db, item) {
|
if let Some(lang_item_name) = lang_attr(db, item) {
|
||||||
self.items.entry(lang_item_name).or_insert_with(|| constructor(item));
|
self.items.entry(lang_item_name).or_insert_with(|| constructor(item));
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,7 @@ impl PerNs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs {
|
pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs {
|
||||||
|
let _p = profile::span("PerNs::filter_visibility");
|
||||||
PerNs {
|
PerNs {
|
||||||
types: self.types.filter(|(_, v)| f(*v)),
|
types: self.types.filter(|(_, v)| f(*v)),
|
||||||
values: self.values.filter(|(_, v)| f(*v)),
|
values: self.values.filter(|(_, v)| f(*v)),
|
||||||
@ -86,6 +87,7 @@ impl PerNs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_items(self) -> impl Iterator<Item = ItemInNs> {
|
pub fn iter_items(self) -> impl Iterator<Item = ItemInNs> {
|
||||||
|
let _p = profile::span("PerNs::iter_items");
|
||||||
self.types
|
self.types
|
||||||
.map(|it| ItemInNs::Types(it.0))
|
.map(|it| ItemInNs::Types(it.0))
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -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> {
|
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
|
// FIXME(#4842): This now depends on CrateDefMap, why not build the entire symbol index from
|
||||||
// that instead?
|
// that instead?
|
||||||
|
|
||||||
@ -321,6 +322,7 @@ impl SymbolIndex {
|
|||||||
|
|
||||||
impl Query {
|
impl Query {
|
||||||
pub(crate) fn search(self, indices: &[&SymbolIndex]) -> Vec<FileSymbol> {
|
pub(crate) fn search(self, indices: &[&SymbolIndex]) -> Vec<FileSymbol> {
|
||||||
|
let _p = profile::span("symbol_index::Query::search");
|
||||||
let mut op = fst::map::OpBuilder::new();
|
let mut op = fst::map::OpBuilder::new();
|
||||||
for file_symbols in indices.iter() {
|
for file_symbols in indices.iter() {
|
||||||
let automaton = fst::automaton::Subsequence::new(&self.lowercased);
|
let automaton = fst::automaton::Subsequence::new(&self.lowercased);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user