Unnamed repository; edit this file 'description' to name the repository.
analysis-stats: expose and print some limited statistics from `hir-def`
David Barsky 2025-03-24
parent 288d783 · commit 7d050fe
-rw-r--r--crates/hir-def/src/item_tree.rs25
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs68
2 files changed, 90 insertions, 3 deletions
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs
index ea87b0f700..2debbb1ee4 100644
--- a/crates/hir-def/src/item_tree.rs
+++ b/crates/hir-def/src/item_tree.rs
@@ -218,6 +218,22 @@ impl ItemTree {
Attrs::filter(db, krate, self.raw_attrs(of).clone())
}
+ /// Returns a count of a few, expensive items.
+ ///
+ /// For more detail, see [`ItemTreeDataStats`].
+ pub fn item_tree_stats(&self) -> ItemTreeDataStats {
+ match self.data {
+ Some(ref data) => ItemTreeDataStats {
+ traits: data.traits.len(),
+ impls: data.impls.len(),
+ mods: data.mods.len(),
+ macro_calls: data.macro_calls.len(),
+ macro_rules: data.macro_rules.len(),
+ },
+ None => ItemTreeDataStats::default(),
+ }
+ }
+
pub fn pretty_print(&self, db: &dyn DefDatabase, edition: Edition) -> String {
pretty::print_item_tree(db, self, edition)
}
@@ -329,6 +345,15 @@ struct ItemTreeData {
}
#[derive(Default, Debug, Eq, PartialEq)]
+pub struct ItemTreeDataStats {
+ pub traits: usize,
+ pub impls: usize,
+ pub mods: usize,
+ pub macro_calls: usize,
+ pub macro_rules: usize,
+}
+
+#[derive(Default, Debug, Eq, PartialEq)]
pub struct ItemTreeSourceMaps {
all_concatenated: Box<[TypesSourceMap]>,
structs_offset: u32,
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index bca44f9588..ec232d8e85 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -3,6 +3,7 @@
use std::{
env, fmt,
+ ops::AddAssign,
time::{SystemTime, UNIX_EPOCH},
};
@@ -129,6 +130,9 @@ impl flags::AnalysisStats {
let mut dep_item_trees = 0;
let mut workspace_item_trees = 0;
+ let mut workspace_item_stats = PrettyItemStats::default();
+ let mut dep_item_stats = PrettyItemStats::default();
+
for source_root_id in source_roots {
let source_root = db.source_root(source_root_id).source_root(db);
for file_id in source_root.iter() {
@@ -137,16 +141,24 @@ impl flags::AnalysisStats {
// measure workspace/project code
if !source_root.is_library || self.with_deps {
let length = db.file_text(file_id).text(db).lines().count();
- db.file_item_tree(EditionedFileId::current_edition(file_id).into());
+ let item_stats = db
+ .file_item_tree(EditionedFileId::current_edition(file_id).into())
+ .item_tree_stats()
+ .into();
workspace_loc += length;
workspace_item_trees += 1;
+ workspace_item_stats += item_stats;
} else {
let length = db.file_text(file_id).text(db).lines().count();
- db.file_item_tree(EditionedFileId::current_edition(file_id).into());
+ let item_stats = db
+ .file_item_tree(EditionedFileId::current_edition(file_id).into())
+ .item_tree_stats()
+ .into();
dep_loc += length;
- dep_item_trees += 1
+ dep_item_trees += 1;
+ dep_item_stats += item_stats;
}
}
}
@@ -161,11 +173,13 @@ impl flags::AnalysisStats {
UsizeWithUnderscore(dep_loc),
UsizeWithUnderscore(dep_item_trees),
);
+ eprintln!(" dependency item stats: {}", dep_item_stats);
eprintln!(
" workspace lines of code: {}, item trees: {}",
UsizeWithUnderscore(workspace_loc),
UsizeWithUnderscore(workspace_item_trees),
);
+ eprintln!(" workspace stats: {}", workspace_item_stats);
// FIXME(salsa-transition): bring back stats for ParseQuery (file size)
// and ParseMacroExpansionQuery (macro expansion "file") size whenever we implement
@@ -1258,6 +1272,7 @@ fn percentage(n: u64, total: u64) -> u64 {
(n * 100).checked_div(total).unwrap_or(100)
}
+#[derive(Default, Debug, Eq, PartialEq)]
struct UsizeWithUnderscore(usize);
impl fmt::Display for UsizeWithUnderscore {
@@ -1282,6 +1297,53 @@ impl fmt::Display for UsizeWithUnderscore {
}
}
+impl std::ops::AddAssign for UsizeWithUnderscore {
+ fn add_assign(&mut self, other: UsizeWithUnderscore) {
+ self.0 += other.0;
+ }
+}
+
+#[derive(Default, Debug, Eq, PartialEq)]
+struct PrettyItemStats {
+ traits: UsizeWithUnderscore,
+ impls: UsizeWithUnderscore,
+ mods: UsizeWithUnderscore,
+ macro_calls: UsizeWithUnderscore,
+ macro_rules: UsizeWithUnderscore,
+}
+
+impl From<hir_def::item_tree::ItemTreeDataStats> for PrettyItemStats {
+ fn from(value: hir_def::item_tree::ItemTreeDataStats) -> Self {
+ Self {
+ traits: UsizeWithUnderscore(value.traits),
+ impls: UsizeWithUnderscore(value.impls),
+ mods: UsizeWithUnderscore(value.mods),
+ macro_calls: UsizeWithUnderscore(value.macro_calls),
+ macro_rules: UsizeWithUnderscore(value.macro_rules),
+ }
+ }
+}
+
+impl AddAssign for PrettyItemStats {
+ fn add_assign(&mut self, rhs: Self) {
+ self.traits += rhs.traits;
+ self.impls += rhs.impls;
+ self.mods += rhs.mods;
+ self.macro_calls += rhs.macro_calls;
+ self.macro_rules += rhs.macro_rules;
+ }
+}
+
+impl fmt::Display for PrettyItemStats {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(
+ f,
+ "traits: {}, impl: {}, mods: {}, macro calls: {}, macro rules: {}",
+ self.traits, self.impls, self.mods, self.macro_calls, self.macro_rules
+ )
+ }
+}
+
// FIXME(salsa-transition): bring this back whenever we implement
// Salsa's memory usage tracking to work with tracked functions.
// fn syntax_len(node: SyntaxNode) -> usize {