mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 21:43:37 +00:00
print memory usage for queries
This commit is contained in:
parent
2ad8220f58
commit
d70520eb38
7 changed files with 101 additions and 13 deletions
|
@ -20,3 +20,4 @@ ra_db = { path = "../ra_db" }
|
||||||
[dependencies.ra_prof]
|
[dependencies.ra_prof]
|
||||||
path = "../ra_prof"
|
path = "../ra_prof"
|
||||||
# features = [ "cpuprofiler" ]
|
# features = [ "cpuprofiler" ]
|
||||||
|
# features = [ "jemalloc" ]
|
||||||
|
|
|
@ -6,9 +6,9 @@ use ra_syntax::AstNode;
|
||||||
|
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
|
|
||||||
pub fn run(verbose: bool, path: &Path, only: Option<&str>) -> Result<()> {
|
pub fn run(verbose: bool, memory_usage: bool, path: &Path, only: Option<&str>) -> Result<()> {
|
||||||
let db_load_time = Instant::now();
|
let db_load_time = Instant::now();
|
||||||
let (host, roots) = ra_batch::load_cargo(path)?;
|
let (mut host, roots) = ra_batch::load_cargo(path)?;
|
||||||
let db = host.raw_database();
|
let db = host.raw_database();
|
||||||
println!("Database loaded, {} roots, {:?}", roots.len(), db_load_time.elapsed());
|
println!("Database loaded, {} roots, {:?}", roots.len(), db_load_time.elapsed());
|
||||||
let analysis_time = Instant::now();
|
let analysis_time = Instant::now();
|
||||||
|
@ -113,5 +113,12 @@ pub fn run(verbose: bool, path: &Path, only: Option<&str>) -> Result<()> {
|
||||||
(num_exprs_partially_unknown * 100 / num_exprs)
|
(num_exprs_partially_unknown * 100 / num_exprs)
|
||||||
);
|
);
|
||||||
println!("Analysis: {:?}, {}", analysis_time.elapsed(), ra_prof::memory_usage());
|
println!("Analysis: {:?}, {}", analysis_time.elapsed(), ra_prof::memory_usage());
|
||||||
|
|
||||||
|
if memory_usage {
|
||||||
|
for (name, bytes) in host.per_query_memory_usage() {
|
||||||
|
println!("{:>8} {}", bytes, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ fn main() -> Result<()> {
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("analysis-stats")
|
SubCommand::with_name("analysis-stats")
|
||||||
.arg(Arg::with_name("verbose").short("v").long("verbose"))
|
.arg(Arg::with_name("verbose").short("v").long("verbose"))
|
||||||
|
.arg(Arg::with_name("memory-usage").long("memory-usage"))
|
||||||
.arg(Arg::with_name("only").short("o").takes_value(true))
|
.arg(Arg::with_name("only").short("o").takes_value(true))
|
||||||
.arg(Arg::with_name("path")),
|
.arg(Arg::with_name("path")),
|
||||||
)
|
)
|
||||||
|
@ -71,9 +72,10 @@ fn main() -> Result<()> {
|
||||||
}
|
}
|
||||||
("analysis-stats", Some(matches)) => {
|
("analysis-stats", Some(matches)) => {
|
||||||
let verbose = matches.is_present("verbose");
|
let verbose = matches.is_present("verbose");
|
||||||
|
let memory_usage = matches.is_present("memory-usage");
|
||||||
let path = matches.value_of("path").unwrap_or("");
|
let path = matches.value_of("path").unwrap_or("");
|
||||||
let only = matches.value_of("only");
|
let only = matches.value_of("only");
|
||||||
analysis_stats::run(verbose, path.as_ref(), only)?;
|
analysis_stats::run(verbose, memory_usage, path.as_ref(), only)?;
|
||||||
}
|
}
|
||||||
("analysis-bench", Some(matches)) => {
|
("analysis-bench", Some(matches)) => {
|
||||||
let verbose = matches.is_present("verbose");
|
let verbose = matches.is_present("verbose");
|
||||||
|
|
|
@ -57,17 +57,21 @@ pub trait InternDatabase: SourceDatabase {
|
||||||
pub trait AstDatabase: InternDatabase {
|
pub trait AstDatabase: InternDatabase {
|
||||||
#[salsa::invoke(crate::source_id::AstIdMap::ast_id_map_query)]
|
#[salsa::invoke(crate::source_id::AstIdMap::ast_id_map_query)]
|
||||||
fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>;
|
fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>;
|
||||||
|
|
||||||
#[salsa::transparent]
|
#[salsa::transparent]
|
||||||
#[salsa::invoke(crate::source_id::AstIdMap::file_item_query)]
|
#[salsa::invoke(crate::source_id::AstIdMap::file_item_query)]
|
||||||
fn ast_id_to_node(&self, file_id: HirFileId, ast_id: ErasedFileAstId) -> TreeArc<SyntaxNode>;
|
fn ast_id_to_node(&self, file_id: HirFileId, ast_id: ErasedFileAstId) -> TreeArc<SyntaxNode>;
|
||||||
|
|
||||||
#[salsa::transparent]
|
#[salsa::transparent]
|
||||||
#[salsa::invoke(crate::ids::HirFileId::parse_or_expand_query)]
|
#[salsa::invoke(crate::ids::HirFileId::parse_or_expand_query)]
|
||||||
fn parse_or_expand(&self, file_id: HirFileId) -> Option<TreeArc<SyntaxNode>>;
|
fn parse_or_expand(&self, file_id: HirFileId) -> Option<TreeArc<SyntaxNode>>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::ids::HirFileId::parse_macro_query)]
|
#[salsa::invoke(crate::ids::HirFileId::parse_macro_query)]
|
||||||
fn parse_macro(&self, macro_file: ids::MacroFile) -> Option<TreeArc<SyntaxNode>>;
|
fn parse_macro(&self, macro_file: ids::MacroFile) -> Option<TreeArc<SyntaxNode>>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::ids::macro_def_query)]
|
#[salsa::invoke(crate::ids::macro_def_query)]
|
||||||
fn macro_def(&self, macro_id: MacroDefId) -> Option<Arc<mbe::MacroRules>>;
|
fn macro_def(&self, macro_id: MacroDefId) -> Option<Arc<mbe::MacroRules>>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::ids::macro_arg_query)]
|
#[salsa::invoke(crate::ids::macro_arg_query)]
|
||||||
fn macro_arg(&self, macro_call: ids::MacroCallId) -> Option<Arc<tt::Subtree>>;
|
fn macro_arg(&self, macro_call: ids::MacroCallId) -> Option<Arc<tt::Subtree>>;
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ use ra_db::{
|
||||||
salsa::{Database, SweepStrategy},
|
salsa::{Database, SweepStrategy},
|
||||||
};
|
};
|
||||||
use ra_syntax::SourceFile;
|
use ra_syntax::SourceFile;
|
||||||
use ra_prof::profile;
|
use ra_prof::{profile, Bytes, memory_usage};
|
||||||
use relative_path::RelativePathBuf;
|
use relative_path::RelativePathBuf;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
|
||||||
|
@ -243,4 +243,65 @@ impl RootDatabase {
|
||||||
self.query(hir::db::InferQuery).sweep(sweep);
|
self.query(hir::db::InferQuery).sweep(sweep);
|
||||||
self.query(hir::db::BodyHirQuery).sweep(sweep);
|
self.query(hir::db::BodyHirQuery).sweep(sweep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn per_query_memory_usage(&mut self) -> Vec<(String, Bytes)> {
|
||||||
|
let mut acc: Vec<(String, Bytes)> = vec![];
|
||||||
|
let sweep = SweepStrategy::default().discard_values().sweep_all_revisions();
|
||||||
|
macro_rules! sweep_each_query {
|
||||||
|
($($q:path)*) => {$(
|
||||||
|
let before = memory_usage().allocated;
|
||||||
|
self.query($q).sweep(sweep);
|
||||||
|
let after = memory_usage().allocated;
|
||||||
|
let q: $q = Default::default();
|
||||||
|
let name = format!("{:?}", q);
|
||||||
|
acc.push((name, before - after));
|
||||||
|
)*}
|
||||||
|
}
|
||||||
|
sweep_each_query![
|
||||||
|
ra_db::ParseQuery
|
||||||
|
ra_db::SourceRootCratesQuery
|
||||||
|
hir::db::AstIdMapQuery
|
||||||
|
hir::db::ParseMacroQuery
|
||||||
|
hir::db::MacroDefQuery
|
||||||
|
hir::db::MacroArgQuery
|
||||||
|
hir::db::MacroExpandQuery
|
||||||
|
hir::db::StructDataQuery
|
||||||
|
hir::db::EnumDataQuery
|
||||||
|
hir::db::TraitDataQuery
|
||||||
|
hir::db::TraitItemsIndexQuery
|
||||||
|
hir::db::RawItemsQuery
|
||||||
|
hir::db::RawItemsWithSourceMapQuery
|
||||||
|
hir::db::CrateDefMapQuery
|
||||||
|
hir::db::ImplsInModuleQuery
|
||||||
|
hir::db::ImplsInModuleWithSourceMapQuery
|
||||||
|
hir::db::GenericParamsQuery
|
||||||
|
hir::db::FnDataQuery
|
||||||
|
hir::db::TypeAliasDataQuery
|
||||||
|
hir::db::ConstDataQuery
|
||||||
|
hir::db::StaticDataQuery
|
||||||
|
hir::db::ModuleLangItemsQuery
|
||||||
|
hir::db::LangItemsQuery
|
||||||
|
hir::db::LangItemQuery
|
||||||
|
hir::db::DocumentationQuery
|
||||||
|
hir::db::ExprScopesQuery
|
||||||
|
hir::db::InferQuery
|
||||||
|
hir::db::TypeForDefQuery
|
||||||
|
hir::db::TypeForFieldQuery
|
||||||
|
hir::db::CallableItemSignatureQuery
|
||||||
|
hir::db::GenericPredicatesQuery
|
||||||
|
hir::db::GenericDefaultsQuery
|
||||||
|
hir::db::BodyWithSourceMapQuery
|
||||||
|
hir::db::BodyHirQuery
|
||||||
|
hir::db::ImplsInCrateQuery
|
||||||
|
hir::db::ImplsForTraitQuery
|
||||||
|
hir::db::AssociatedTyDataQuery
|
||||||
|
hir::db::TraitDatumQuery
|
||||||
|
hir::db::StructDatumQuery
|
||||||
|
hir::db::ImplDatumQuery
|
||||||
|
hir::db::ImplementsQuery
|
||||||
|
hir::db::NormalizeQuery
|
||||||
|
];
|
||||||
|
acc.sort_by_key(|it| std::cmp::Reverse(it.1));
|
||||||
|
acc
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,6 +270,10 @@ impl AnalysisHost {
|
||||||
pub fn collect_garbage(&mut self) {
|
pub fn collect_garbage(&mut self) {
|
||||||
self.db.collect_garbage();
|
self.db.collect_garbage();
|
||||||
}
|
}
|
||||||
|
/// NB: this clears the database
|
||||||
|
pub fn per_query_memory_usage(&mut self) -> Vec<(String, ra_prof::Bytes)> {
|
||||||
|
self.db.per_query_memory_usage()
|
||||||
|
}
|
||||||
pub fn raw_database(&self) -> &(impl hir::db::HirDatabase + salsa::Database) {
|
pub fn raw_database(&self) -> &(impl hir::db::HirDatabase + salsa::Database) {
|
||||||
&self.db
|
&self.db
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,21 +27,23 @@ impl fmt::Display for MemoryUsage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
|
||||||
pub struct Bytes(usize);
|
pub struct Bytes(usize);
|
||||||
|
|
||||||
impl fmt::Display for Bytes {
|
impl fmt::Display for Bytes {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let bytes = self.0;
|
let bytes = self.0;
|
||||||
if bytes < 4096 {
|
let mut value = bytes;
|
||||||
return write!(f, "{} bytes", bytes);
|
let mut suffix = "b";
|
||||||
|
if value > 4096 {
|
||||||
|
value /= 1024;
|
||||||
|
suffix = "kb";
|
||||||
|
if value > 4096 {
|
||||||
|
value /= 1024;
|
||||||
|
suffix = "mb";
|
||||||
}
|
}
|
||||||
let kb = bytes / 1024;
|
|
||||||
if kb < 4096 {
|
|
||||||
return write!(f, "{}kb", kb);
|
|
||||||
}
|
}
|
||||||
let mb = kb / 1024;
|
f.pad(&format!("{}{}", value, suffix))
|
||||||
write!(f, "{}mb", mb)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,3 +52,10 @@ impl std::ops::AddAssign<usize> for Bytes {
|
||||||
self.0 += x;
|
self.0 += x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::ops::Sub for Bytes {
|
||||||
|
type Output = Bytes;
|
||||||
|
fn sub(self, rhs: Bytes) -> Bytes {
|
||||||
|
Bytes(self.0 - rhs.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue